【问题标题】:Hide a swing component without revalidating the layout?隐藏一个摆动组件而不重新验证布局?
【发布时间】:2014-11-11 18:29:10
【问题描述】:

如果我设置了一个带有一些组件和一个布局管理器的 JFrame,它最初看起来非常好,然后由于某些条件(例如,单击一个按钮)我隐藏了其中一个组件 - 布局管理器将所有组件又来了。

查看示例代码 - 最初出现 3 个按钮。当您单击“隐藏”按钮时,“隐藏”按钮会被隐藏 - 但两个外部按钮会挤在一起。当您单击显示按钮时,它们会再次分开以腾出空间。我怎样才能阻止这种情况的发生,以便在我调用 pack() 之后,组件保持在原来的位置,无论它们后来是否被隐藏?

在我的真实代码中,我使用 GridBagLayout 执行此操作,但在下面的示例中使用了 FlowLayout,因为它的代码更简单、更少,并且表现出完全相同的行为。

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

这似乎与这里完全相反的问题 - Hide a button from Layout in Java Swing - 抱怨隐藏按钮 do 仍然占用空间:) 但是那里没有示例代码显示它以这种方式工作。

非常感谢您的任何建议:)

例子:

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

【问题讨论】:

    标签: java swing layout hide invisible


    【解决方案1】:

    您可以使用CardLayout,然后将按钮与空的 JPanel 交换。

    阅读 How to Use CardLayout 上的 Swing 教程部分,了解更多信息和示例。

    【讨论】:

    • 是的,我经常使用 CardLayouts,但不适用于这种情况。这实际上是一个不错的主意,因为即使按钮​​不可见, CardLayout 也会根据按钮(或其他)调整自己的大小,因此不会让人觉得它在滥用布局管理器。
    • 我构建了一个 HideableComponent 类,它就是这样做的 - 用卡片布局将任何组件包装在面板中,因此只需调用 .setHidden (true/false) 即可,因此无需知道在涵盖了它是通过 CardLayout 实现的,它完美地工作:) 所以可以这样做,例如新的 HideableComponent(新的 JButton(动作))。如果有兴趣这里的代码 - sourceforge.net/p/momime/code/HEAD/tree/Java/MoMIMEClient/trunk/…
    【解决方案2】:

    问题出在布局管理器上,这里并不是真正的问题,因为它只是在做自己的工作。您可以将布局设置为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 关闭时退出;没有它,程序仍然在后台运行。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多