如果我用一些组件和布局管理器设置一个JFrame,它最初看起来非常好,然后由于某些条件(比如,点击一个按钮),我隐藏了其中一个组件 - 布局管理器将所有组件洗牌组件再次出现。
参见示例代码 - 最初出现3个按钮。单击“隐藏”按钮时,“隐藏”按钮将被隐藏 - 但两个外部按钮则会挤压在一起。单击“显示”按钮时,它们会再次分开以腾出空间。如何阻止这种情况发生,以便在我调用pack()之后,组件会保留在它们的位置,无论它们以后是否被隐藏?
在我的实际代码中,我使用GridBagLayout执行此操作,但在下面的示例中使用了FlowLayout,因为它更简单,代码更少,并且显示完全相同的行为。
我只能想到这样做的讨厌方法,比如使用.setEnabled(false)而不是.setVisible(false),然后覆盖组件的paintComponent()方法,以便在组件不被绘制时禁用。
这似乎是完全相反的问题 - Hide a button from Layout in Java Swing - 在哪里抱怨隐藏按钮做仍然占用空间:)但是那里没有示例代码可供展示它以这种方式工作。
非常感谢任何建议:)
示例:
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 ();
}
});
}
}
答案 0 :(得分:4)
您可以使用CardLayout
,然后将该按钮与空的JPanel交换。
阅读How to Use CardLayout上Swing教程中的部分,了解更多信息和示例。
答案 1 :(得分:1)
问题是布局管理器,这不是一个真正的问题,因为它只是在做它的工作。您可以将布局设置为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
关闭时退出;没有它,程序仍然在后台运行。