java removeAll 在下次验证时不删除?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/5812002/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 12:54:05  来源:igfitidea点击:

removeAll not removing at next validate?

javaswing

提问by pstanton

Can someone explain why the following doesn't work as I expect?

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

Pressing the button 'should' result in the display only containing the (empty) JScrollPane, ie the input field and button should disappear. However they stay until the component is resized...

按下按钮“应该”导致显示仅包含(空)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);
}

Thanks for your help. p.

谢谢你的帮助。p.

回答by camickr

When updating a visible GUI the code should be:

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

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

回答by trashgod

The revalidate()method marks components as needing to be laid out, but until something triggers repaint()you won't see any change. Resizing the parent window is one such trigger; switching applications is another. In this previous version, note how setSize()on the panel obviates the need for repaint(). Similarly, this examplechanges the layout in resetGame().

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

The article Painting in AWT and Swinggoes into more detail.

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

回答by Kris Babic

You can execute panel.repaint()as specified in the comment by @Jeremy, however, the UI will still change when you resize the window. The reason being that the removal of the elements from the JPanel will cause the panel to resize. A repaint operation will not cause the panel to resize until the JFrame rechecks its layout (as happens on a window resize).

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

To make sure that the layout is correctly layed out on a change, you can call frame.validate(). This operation will cause the JFrame to revalidate itself and all child components, which is the same operation that is taking place during a window resize event. To execute this method in your code you would need to change JFrame frameto final, i.e.,

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

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