Java 在带边框布局的JPanel上浮动JPanel
我有一个名为Java 在带边框布局的JPanel上浮动JPanel,java,swing,layout,Java,Swing,Layout,我有一个名为pnlMain的JPanel,布局设置为BorderLayout。面板内部有三个JPanel添加到PAGE\u START、中心和PAGE\u END。现在,我的要求是,如果单击设置按钮,它将在pnlMain上方显示一个透明的JPanel。这个透明的面板将包含一个不透明的、较小的、居中的面板,其中将包含设置内容 我知道我可以使用JLayeredPane来实现这一点,但查看it时发现,您只能使用绝对定位来放置不同深度的组件,我知道这是非常不鼓励的 是否有其他方法可以在不使用绝对定位的情
pnlMain
的JPanel
,布局设置为BorderLayout
。面板内部有三个JPanel
添加到PAGE\u START
、中心
和PAGE\u END
。现在,我的要求是,如果单击设置按钮,它将在pnlMain
上方显示一个透明的JPanel
。这个透明的面板将包含一个不透明的、较小的、居中的面板,其中将包含设置内容
我知道我可以使用JLayeredPane
来实现这一点,但查看it时发现,您只能使用绝对定位来放置不同深度的组件,我知道这是非常不鼓励的
是否有其他方法可以在不使用绝对定位的情况下执行此操作?您可以使用父框架的玻璃窗格,这将允许您向其添加看起来覆盖在主要内容上的组件 基本上,我会创建一个
JPanel
,并将其设置为透明(setOpaque(false)
)。我会将其布局管理器设置为类似于GridBagLayout
(因为它将使用子组件的首选大小,并自动将其置于父容器的中心)
在此面板上,我将添加设置
面板
最后,我将父框架的玻璃窗格设置为第一个(背衬)窗格,并使其可见
frame.getRootPane().setGlassPane(backingPane); // Or similar
看看
已更新
如果你不能自己使用顶层框架的玻璃窗格,那么你需要伪造它
此示例基本上使用了一个JLayeredPane
,后面是一个GridBagLayout
如果将鼠标侦听器
和键侦听器
添加到背景窗格,则可以使用到子组件的事件
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.EventQueue;
import java.awt.Graphics;
import java.awt.GridBagConstraints;
import java.awt.GridBagLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JLayeredPane;
import javax.swing.JPanel;
import javax.swing.UIManager;
import javax.swing.UnsupportedLookAndFeelException;
import javax.swing.border.EmptyBorder;
public class FloatingPane {
public static void main(String[] args) {
new FloatingPane();
}
public FloatingPane() {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
try {
UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} catch (ClassNotFoundException | InstantiationException | IllegalAccessException | UnsupportedLookAndFeelException ex) {
}
final WorkPane workPane = new WorkPane();
JButton settings = new JButton("Settings");
settings.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
workPane.toggleSettings();
}
});
JFrame frame = new JFrame("Testing");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLayout(new BorderLayout());
frame.add(workPane);
frame.add(settings, BorderLayout.SOUTH);
frame.pack();
frame.setLocationRelativeTo(null);
frame.setVisible(true);
}
});
}
public class WorkPane extends JLayeredPane {
private final BackingPane backingPane;
public WorkPane() {
setLayout(new GridBagLayout());
GridBagConstraints gbc = new GridBagConstraints();
gbc.gridx = 1;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.fill = GridBagConstraints.BOTH;
add(createLabel("Center", Color.BLUE), gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 0;
gbc.weighty = 0;
gbc.fill = GridBagConstraints.VERTICAL;
add(createLabel("Left", Color.RED), gbc);
gbc.gridx = 2;
add(createLabel("Right", Color.GREEN), gbc);
gbc.gridx = 0;
gbc.gridy = 0;
gbc.weightx = 1;
gbc.weighty = 1;
gbc.gridheight = GridBagConstraints.REMAINDER;
gbc.gridwidth = GridBagConstraints.REMAINDER;
gbc.fill = GridBagConstraints.BOTH;
backingPane = new BackingPane();
backingPane.add(new SettingsPane());
backingPane.setVisible(false);
add(backingPane, gbc);
setLayer(backingPane, DEFAULT_LAYER + 1);
}
public void toggleSettings() {
backingPane.setVisible(!backingPane.isVisible());
}
protected JLabel createLabel(String text, Color bg) {
JLabel label = new JLabel(text);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBackground(bg);
return label;
}
}
public class BackingPane extends JPanel {
public BackingPane() {
setLayout(new GridBagLayout());
setOpaque(false);
}
@Override
protected void paintComponent(Graphics g) {
super.paintComponent(g);
g.setColor(new Color(128, 128, 128, 192));
g.fillRect(0, 0, getWidth(), getHeight());
}
}
public class SettingsPane extends JPanel {
public SettingsPane() {
setBorder(new EmptyBorder(10, 10, 10, 10));
add(new JLabel("Settings"));
}
}
}
另一种解决方案可能是通过拍摄当前面板的快照,并使用
CardLayout
,翻转到“设置”窗格,将快照用作“设置”窗格的背景图像(然后可以将效果应用于灰度缩放和模糊等)FYI-您可以将布局管理器与JLayeredPane
一起使用,但您需要一个布局管理器,它允许您将组件放置在彼此的顶部,如GridBagLayout
,但可能有更简单的解决方案:d至少今天我帮助了一些人@MadProgrammer在JPanel
层中是否有这样做的方法,因为我的JPanel
可能嵌入在一个更大的帧中,这意味着如果我调用getRootPane()
它将返回更大的帧,那么玻璃窗格将应用于更大的帧。不是吗?@onepotato,但据我所知,Java7使用@mKorbel时,JLayer
是一个装饰器,它不允许与组件进行实时交互(东西刚刚画好)-可能是错误的,因为我只使用了JXLayer
@尝试向UI添加其他组件并触发一些重绘,特别是那些应该发生在组件下面的。你可能不总是会遇到小故障,但当你遇到时,它将是非常棒的,这是关于这个问题的不止几个问题的来源