【问题标题】:removeAll not removing at next validate?removeAll 在下次验证时不删除?
【发布时间】:2011-09-05 19:46:12
【问题描述】:

有人可以解释为什么以下内容不能按我的预期工作吗?

按下按钮“应该”会导致显示只包含(空的)JScrollPane,即输入字段和按钮应该消失。但是,它们会一直保留到调整组件大小...

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);
}

感谢您的帮助。 p.

【问题讨论】:

  • 改用panel.repaint()
  • sscce

标签: java swing


【解决方案1】:

更新可见 GUI 时,代码应为:

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

【讨论】:

    【解决方案2】:

    revalidate() 方法将组件标记为需要布局,但在触发 repaint() 之前,您不会看到任何更改。调整父窗口的大小就是这样的触发器之一;切换应用程序是另一个。在之前的version 中,请注意面板上的setSize() 如何消除对repaint() 的需要。同样,这个example 改变了resetGame() 中的布局。

    文章Painting in AWT and 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();
                }
            });
        }
    }
    

    【讨论】:

    • 另见DynamicLayout
    • 但是,哪个理智的应用程序代码会调用 setSize ;-) 这只是另一个将组件排队等待重绘的触发器,因此最好坚持直接路径而不是偏差。
    • @kleopatra:非常正确;只是一个示例,旨在照亮管道。正在更新……
    【解决方案3】:

    您可以按照@Jeremy 评论中的说明执行panel.repaint(),但是,当您调整窗口大小时,UI 仍然会发生变化。原因是从 JPanel 中删除元素会导致面板调整大小。在 JFrame 重新检查其布局之前,重绘操作不会导致面板调整大小(就像在窗口调整大小时发生的那样)。

    要确保布局在更改时正确布局,您可以致电frame.validate()。此操作将导致 JFrame 重新验证自身和所有子组件,这与在窗口调整大小事件期间发生的操作相同。要在您的代码中执行此方法,您需要将 JFrame frame 更改为 final,即

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

    【讨论】:

    • 我认为删除不会触发调整大小;我认为调整大小会通过父窗口的ComponentListener 触发repaint()。通过窗口的WindowListener 也可以切换应用程序。此外,除非我同时更改某些组件的大小、位置或布局,否则我无法重现您的 frame.validate() 结果。
    • @trashgod 您是否看到额外的调整大小(又名:Kris 的“布局正确布局”)取决于面板是否有一个父级,即validationRoot(在顶级之下)。为了完全确保在所有顶级容器中重新评估布局,验证该容器(也是最顶级的validationRoot)是要走的路
    • 不需要(最终或其他)对框架的引用 - SwingUtilities.windowForComponent 是你的朋友 :-)
    猜你喜欢
    • 2014-09-28
    • 2016-06-27
    • 2015-05-01
    • 2016-04-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-02-11
    • 2018-03-22
    相关资源
    最近更新 更多