【发布时间】:2017-07-13 19:21:57
【问题描述】:
受这个问题的启发 JLayeredPane with a LayoutManager 我正在尝试让 JLayeredPane 与 GridBagLayout 一起使用。
这是自定义的 LayeredPane 类:
class StackConstraints {
public final int layer;
public final Object layoutConstraints;
public StackConstraints(int layer, Object layoutConstraints) {
this.layer = layer;
this.layoutConstraints = layoutConstraints;
}
}
class LXLayeredPane extends JLayeredPane {
private static final long serialVersionUID = 1946283565823567689L;
@Override
protected void addImpl(Component comp, Object constraints, int index) {
int layer = 0;
int pos = 0;
Object constr = null;
if (constraints instanceof StackConstraints) {
layer = ((StackConstraints) constraints).layer;
constr = ((StackConstraints) constraints).layoutConstraints;
} else {
layer = getLayer(comp);
constr = constraints;
}
pos = insertIndexForLayer(layer, index);
super.addImpl(comp, constr, pos);
setLayer(comp, layer, pos);
comp.validate();
comp.repaint();
}
}
这是一个简单的演示(类似于标准的 JLayeredPane 演示,但适用于 GridBagConstraints 并去除了不必要的东西)。
public class LayeredPaneDemo extends JPanel implements ActionListener {
private final Color[] layerColors = { Color.yellow, Color.magenta, Color.cyan, Color.red, Color.green, Color.blue };
private final JLayeredPane layeredPane;
private final List<JLabel> labels;
private JButton update;
public LayeredPaneDemo() {
setLayout(new BoxLayout(this, BoxLayout.PAGE_AXIS));
labels = new ArrayList<>();
layeredPane = new LXLayeredPane();
layeredPane.setPreferredSize(new Dimension(400, 410));
layeredPane.setBorder(BorderFactory.createTitledBorder("Click to change colors"));
// Add several labels to the layered pane.
layeredPane.setLayout(new GridBagLayout());
for (int i = 0; i < layerColors.length; i++) {
JLabel label = createColoredLabel("Test", layerColors[i]);
labels.add(label);
layeredPane.add(label, new StackConstraints(i, gbc(i)));
}
// Add control pane and layered pane to this JPanel.
add(Box.createRigidArea(new Dimension(0, 10)));
add(createControlPanel());
add(Box.createRigidArea(new Dimension(0, 10)));
add(layeredPane);
}
private GridBagConstraints gbc(int i) {
return new GridBagConstraints(i, i, 2, 2, 0.0, 0.0, GridBagConstraints.CENTER, GridBagConstraints.BOTH,
new Insets(0, 0, 0, 0), 0, 0);
}
// Create and set up a colored label.
private JLabel createColoredLabel(String text, Color color) {
JLabel label = new JLabel(text);
label.setVerticalAlignment(JLabel.TOP);
label.setHorizontalAlignment(JLabel.CENTER);
label.setOpaque(true);
label.setBackground(color);
label.setForeground(Color.black);
label.setBorder(BorderFactory.createLineBorder(Color.black));
label.setPreferredSize(new Dimension(240, 240));
return label;
}
// Create the control pane for the top of the frame.
private JPanel createControlPanel() {
update = new JButton("Update");
update.addActionListener(this);
update.setActionCommand("UPDATE");
JPanel controls = new JPanel();
controls.add(update);
controls.setBorder(BorderFactory.createTitledBorder("Choose Duke's Layer and Position"));
return controls;
}
@Override
public void actionPerformed(ActionEvent e) {
Color prev = labels.get(labels.size() - 1).getBackground();
for (int i = labels.size() - 1; i > 0; --i) {
labels.get(i).setBackground(labels.get(i - 1).getBackground());
labels.get(i).validate();
labels.get(i).repaint();
}
labels.get(0).setBackground(prev);
labels.get(0).validate();
labels.get(0).repaint();
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("LayeredPaneDemo2");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
JComponent newContentPane = new LayeredPaneDemo();
newContentPane.setOpaque(true);
frame.setContentPane(newContentPane);
frame.pack();
frame.setVisible(true);
}
public static void main(String[] args) {
javax.swing.SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
createAndShowGUI();
}
});
}
}
我的问题是我添加了 6 个(六个!)标签,但只显示了 5 个(五个!)。第 0 个就在某处消失了。这是什么原因?
编辑: 追求的最初动机是将一个(部分透明)组件放在另一个组件之上,就像这个屏幕截图一样 显示 17:00:09 的标签具有透明背景并放置在图表组件的顶部。需要 GridBagLayout 才能将其准确放置在图表的顶部中间。
【问题讨论】:
-
I'm trying to get the JLayeredPane to work with the GridBagLayout.- 为什么?这是两个不同的概念。分层窗格用于显示层中的组件。 GridBagLayout 用于在面板上显示组件。您要解决的确切问题是什么?我看不出您实现的行为与原始分层窗格演示的行为有何不同。 -
编辑了答案以解释动机。我本可以为每个不同的图层使用具有透明背景的面板和 GridBagLayout,但它们只是不想正常工作。
-
but they just didn't want to work properly- 这并没有定义问题。您有两个潜在问题,1)分层窗格代码或 2)每个面板上用于 GridBagLayout 的约束。发布一个正确的minimal reproducible example 来证明问题。从图片中我无法判断堆叠的组件或实际问题是什么。 -
亲爱的罗伯特,我可能在之前的评论中说错了。我发布的屏幕截图来自我最终通过使用多个面板开发的 GUI,每个面板都带有
GridBagLayout,因此已经达到了最初的目标。但是,在尝试通过扩展JLayeredPane并使用它来解决问题时,我遇到了JLabels 的上述问题。我只是想了解这种特殊行为的原因:我的示例中是否有错误,或者是否存在我无法混合图层和GridBagLayout的根本原因? -
它认为第一个标签与下一个标签被分配相同的位置(x,y),并且被认为完全被遮挡,因此不被绘制。因此错误出现在布局阶段,而不是在绘画过程中
标签: java swing layout-manager gridbaglayout jlayeredpane