Java 隐藏swing组件而不重新验证布局?

Java 隐藏swing组件而不重新验证布局?,java,swing,layout,hide,invisible,Java,Swing,Layout,Hide,Invisible,如果我用一些组件和布局管理器设置了一个JFrame,最初看起来非常好,但后来由于某种情况(比如,单击按钮),我会隐藏其中一个组件——布局管理器会再次洗牌所有组件 请参见示例代码-最初显示3个按钮。单击“隐藏”按钮时,“隐藏”按钮被隐藏,但两个外部按钮会挤压在一起。单击“显示”按钮时,它们会再次分开以腾出空间。我如何才能阻止这种情况的发生,以便在调用pack()之后,组件保持在原来的位置,而不管它们以后是否被隐藏 在我的实际代码中,我使用GridBagLayout来实现这一点,但在下面的示例中使用

如果我用一些组件和布局管理器设置了一个JFrame,最初看起来非常好,但后来由于某种情况(比如,单击按钮),我会隐藏其中一个组件——布局管理器会再次洗牌所有组件

请参见示例代码-最初显示3个按钮。单击“隐藏”按钮时,“隐藏”按钮被隐藏,但两个外部按钮会挤压在一起。单击“显示”按钮时,它们会再次分开以腾出空间。我如何才能阻止这种情况的发生,以便在调用pack()之后,组件保持在原来的位置,而不管它们以后是否被隐藏

在我的实际代码中,我使用GridBagLayout来实现这一点,但在下面的示例中使用了FlowLayout,因为它更简单,代码更少,并且显示了完全相同的行为

我只能想到一些令人讨厌的方法,比如使用.setEnabled(false)而不是.setVisible(false),然后重写组件的paintComponent()方法,在禁用组件时不绘制组件

这里的问题似乎正好相反——哪里的人抱怨隐藏的按钮仍然占用空间:)但是那里没有示例代码显示它以这种方式工作

非常感谢您的建议:)

例如:

import java.awt.FlowLayout;
import java.awt.event.ActionEvent;

import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.SwingUtilities;

public class RevalidateWhenSetChildInvisibleExample
{
    private JButton button1;
    private JButton button2;
    private JButton button3;

    public void run ()
    {
        // Set up action
        Action hideButtonAction = new AbstractAction ()
        {
            @Override
            public void actionPerformed (ActionEvent e)
            {
                button2.setVisible (false);
            }
        };
        hideButtonAction.putValue (Action.NAME, "Hide");

        Action showButtonAction = new AbstractAction ()
        {
            @Override
            public void actionPerformed (ActionEvent e)
            {
                button2.setVisible (true);
            }
        };
        showButtonAction.putValue (Action.NAME, "Show");

        // Set up buttons
        button1 = new JButton ("Dummy");
        button2 = new JButton (hideButtonAction);
        button3 = new JButton (showButtonAction);

        // Set up content pane
        JPanel contentPane = new JPanel ();
        contentPane.setLayout (new FlowLayout ());
        contentPane.add (button1);
        contentPane.add (button2);
        contentPane.add (button3);

        // Set up frame
        JFrame frame = new JFrame ();
        frame.setContentPane (contentPane);
        frame.pack ();
        frame.setVisible (true);
    }

    public static void main (String args [])
    {
        SwingUtilities.invokeLater (new Runnable ()
        {
            public void run ()
            {
                new RevalidateWhenSetChildInvisibleExample ().run ();
            }
        });
    }
}

您可以使用
卡片布局
,然后将按钮与空JPanel交换


有关更多信息和示例,请阅读上Swing教程的部分。

您可以使用
卡片布局,然后将按钮与空JPanel交换


有关更多信息和示例,请阅读上Swing教程的部分。

问题在于布局管理器,它在这里并不是一个真正的问题,因为它只是在完成它的工作。您可以将布局设置为
null
,然后为每个按钮设置边界;这样,除非你改变他们的位置,否则他们永远不会移动

panel.setLayout(null);
button1.setBounds(10,10,50,20);
button2.setBounds(70,10,50,20);
button3.setBounds(xPos,yPos,width,height);
另一种方法是使用
GridLayout

contentPane.setLayout(new GridLayout());
我测试了它,它工作得很好,因为组件没有被移除,所以它保持不变

此外,您还应在代码中添加以下内容:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

这使得程序在
JFrame
关闭时退出;没有它,程序仍然在后台运行。

问题在于布局管理器,它在这里不是真正的问题,因为它只是在完成它的工作。您可以将布局设置为
null
,然后为每个按钮设置边界;这样,除非你改变他们的位置,否则他们永远不会移动

panel.setLayout(null);
button1.setBounds(10,10,50,20);
button2.setBounds(70,10,50,20);
button3.setBounds(xPos,yPos,width,height);
另一种方法是使用
GridLayout

contentPane.setLayout(new GridLayout());
我测试了它,它工作得很好,因为组件没有被移除,所以它保持不变

此外,您还应在代码中添加以下内容:

frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

这使得程序在
JFrame
关闭时退出;没有它,程序仍然在后台运行。

是的,我经常使用CardLayouts,但不适用于此场景。这实际上是一个不错的主意,因为CardLayout会根据按钮(或任何东西)来调整大小,即使按钮不可见,所以它也不会滥用布局管理器。我构建了一个HideableComponent类,它就是这样做的——用CardLayout包装面板中的任何组件,因此可以调用.setHidden(true/false)在它上面,所以不必知道它是通过CardLayout实现的,并且它工作得非常完美:)所以可以这样做,例如新的HideableComponent(新的JButton(action))。如果有兴趣,这里的代码-是的,我用了很多卡片布局,但不是这个场景。这实际上是一个不错的主意,因为CardLayout会根据按钮(或任何东西)来调整大小,即使按钮不可见,所以它也不会滥用布局管理器。我构建了一个HideableComponent类,它就是这样做的——用CardLayout包装面板中的任何组件,因此可以调用.setHidden(true/false)在它上面,所以不必知道它是通过CardLayout实现的,并且它工作得非常完美:)所以可以这样做,例如新的HideableComponent(新的JButton(action))。如果有兴趣,这里的代码-