如何从 paintComponent() 向 GridBagLayout 添加元素
How to add elements to GridBagLayout from paintComponent()
在下面的代码中,在构造函数中标签被正确创建并显示在屏幕上。请注意,它已添加到 GridBagLayout()
布局管理器中。然后,在我们从 JPanel 扩展覆盖的 paintComponent()
方法中,我们重置 JPanel 的内容并再次添加标签。但是,这次标签没有显示在屏幕上。我希望它能正常添加,但事实并非如此。为什么会这样?
public class MyPanel extends JPanel {
private final GridBagConstraints grid = new GridBagConstraints();
public MyPanel () {
setBounds(200, 200, 1000, 1000);
setLayout(new GridBagLayout());
setOpaque(false);
setVisible(false);
grid.anchor = GridBagConstraints.PAGE_END;
JLabel oldLabel = new JLabel("This is an old Label");
add(oldLabel, grid);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
removeAll();
JLabel newLabel = new JLabel("This is a new Label");
add(newLabel, grid);
revalidate();
repaint();
}
}
在这个例子中,组件是已知的,但在我的情况下,我有一个可变数量的组件,这些组件是事先不知道的,并且在程序期间会发生变化。
喜欢我的问题的评论好心说,我的做法是不正确的。
在任何情况下 paintComponent
都不应创建、添加或删除组件。绘画是由系统触发的,原因有很多,包括看似微不足道的事件,例如将鼠标移到 window 上。此外,永远不要从 paintComponent 方法中调用 repaint
;这会强制 Swing 最终再次调用 paintComponent,这意味着您已经创建了一个无限循环。
解决方案是将组件添加到面板并在面板上调用 revalidate()
。
在下面的代码中,在构造函数中标签被正确创建并显示在屏幕上。请注意,它已添加到 GridBagLayout()
布局管理器中。然后,在我们从 JPanel 扩展覆盖的 paintComponent()
方法中,我们重置 JPanel 的内容并再次添加标签。但是,这次标签没有显示在屏幕上。我希望它能正常添加,但事实并非如此。为什么会这样?
public class MyPanel extends JPanel {
private final GridBagConstraints grid = new GridBagConstraints();
public MyPanel () {
setBounds(200, 200, 1000, 1000);
setLayout(new GridBagLayout());
setOpaque(false);
setVisible(false);
grid.anchor = GridBagConstraints.PAGE_END;
JLabel oldLabel = new JLabel("This is an old Label");
add(oldLabel, grid);
}
@Override
public void paintComponent(Graphics g) {
super.paintComponent(g);
removeAll();
JLabel newLabel = new JLabel("This is a new Label");
add(newLabel, grid);
revalidate();
repaint();
}
}
在这个例子中,组件是已知的,但在我的情况下,我有一个可变数量的组件,这些组件是事先不知道的,并且在程序期间会发生变化。
喜欢我的问题的评论好心说,我的做法是不正确的。
在任何情况下 paintComponent
都不应创建、添加或删除组件。绘画是由系统触发的,原因有很多,包括看似微不足道的事件,例如将鼠标移到 window 上。此外,永远不要从 paintComponent 方法中调用 repaint
;这会强制 Swing 最终再次调用 paintComponent,这意味着您已经创建了一个无限循环。
解决方案是将组件添加到面板并在面板上调用 revalidate()
。