removeAll在下次validation时不会删除?

有人可以解释为什么以下不能如我所料?

按下button'should'将导致只包含(空的)JScrollPane的显示,即input栏和button应该消失。 然而,他们留下来,直到组件被resize…

public static void main(String[] args) { JFrame frame = new JFrame("test"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); final JPanel panel = new JPanel(); Container cp = frame.getContentPane(); cp.setLayout(new FlowLayout()); cp.add(new JScrollPane(panel)); Component textField = new JTextField("i am input"); JButton button = new JButton(new AbstractAction("i am pressy") { @Override public void actionPerformed(ActionEvent e) { // this is already on the EDT panel.removeAll(); panel.revalidate(); } }); panel.setLayout(new FlowLayout()); panel.add(textField); panel.add(button); frame.pack(); frame.setVisible(true); } 

谢谢你的帮助。 页。

更新可视化GUI时,代码应该是:

 panel.revalidate(); panel.repaint(); // sometimes needed, this appears to be one of them 

revalidate()方法将组件标记为需要布局,但是直到某些事件触发repaint()您将看不到任何更改。 调整父窗口的大小就是这样一个触发器。 切换应用程序是另一个 在以前的版本中 ,请注意面板上的setSize()如何避免repaint()的需要。 同样,这个例子改变了resetGame()的布局。

AWT和Swing中的绘画”更详细。

 import java.awt.EventQueue; import java.awt.event.ActionEvent; import javax.swing.AbstractAction; import javax.swing.JButton; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JTextField; import javax.swing.WindowConstants; /** @see https://stackoverflow.com/questions/5812002 */ public class RevalidateTest { private static JPanel panel = new JPanel(); // default FlowLayout private static JTextField text = new JTextField("Text field"); private static JButton clear = new JButton(new AbstractAction("Clear") { @Override public void actionPerformed(ActionEvent e) { panel.removeAll(); panel.add(reset); panel.revalidate(); panel.repaint(); } }); private static JButton reset = new JButton(new AbstractAction("Reset") { @Override public void actionPerformed(ActionEvent e) { panel.removeAll(); panel.add(text); panel.add(clear); panel.revalidate(); panel.repaint(); } }); static void createAndShowGUI() { JFrame frame = new JFrame("Test"); frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); panel.add(text); panel.add(clear); frame.add(panel); // default BorderLayout center frame.pack(); frame.setLocationRelativeTo(null); frame.setVisible(true); } public static void main(String[] args) { EventQueue.invokeLater(new Runnable() { @Override public void run() { createAndShowGUI(); } }); } } 

您可以panel.repaint()的注释中的指定执行panel.repaint() ,但是,当您调整窗口大小时,UI仍会改变。 原因是从JPanel中删除元素会导致面板resize。 重绘操作不会导致面板resize,直到JFrame重新检查其布局为止(如调整窗口大小时)。

为了确保布局正确地布局在一个变化上,你可以调用frame.validate() 。 此操作将导致JFrame重新validation自身和所有子组件,这与窗口resize事件期间发生的操作是相同的。 要在您的代码中执行此方法,您需要将JFrame frame更改为final,即,

 final JFrame frame = new JFrame("test");