我正在尝试使用Swing布局在控件上方留出一个间隙,该控件是根据窗口的当前大小计算出来的。它基本上有效,除了控件只在窗口水平调整大小时移动 - 如果我垂直调整大小,它会保持原样 - 然后水平调整1个像素,它会捕捉到正确的位置。任何人都可以解释为什么在我只是垂直调整大小时会忽略调整大小?
我已经证明,仍然在垂直调整大小上调用componentResized(),而contentPane.getWidth()和contentPane.getHeight()仍然给出了正确的值。因此Dimension的大小正确设置,只是被忽略。它就像我需要调用contentPane.payAttentionToUpdatesSizesOfYourComponents(),但我找不到任何方法来执行此操作。 contentPane.invalidate()无效。
还注意到,如果我去掉BorderLayout,并在contentPane中直接设置BoxLayout,那么它可以按我的意愿工作。然而虽然这对于这个小例子来说很好,但我遇到这个问题的真实窗口有一些组件在一个JPanel设置在NORTH上面有一个间隙,另一个JPanel中的一些组件设置在SOUTH,下面有一个间隙,而BorderLayout是唯一的方式我可以正确定位这些,所以我不能把它剥掉。
欢迎任何建议或建议!
import java.awt.BorderLayout;
import java.awt.Dimension;
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import javax.swing.Box.Filler;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.WindowConstants;
public final class ResizeOnlyWorksHorizontally
{
public static final void main (final String [] args)
{
final JFrame frame = new JFrame ();
frame.setDefaultCloseOperation (WindowConstants.EXIT_ON_CLOSE);
final JPanel contentPane = new JPanel ();
frame.setContentPane (contentPane);
contentPane.setLayout (new BorderLayout ());
final JPanel top = new JPanel ();
top.setLayout (new BoxLayout (top, BoxLayout.Y_AXIS));
contentPane.add (top, BorderLayout.NORTH);
// Put a space, then a label below it
final Dimension startSpace = new Dimension (0, 0);
final Filler filler = new Filler (startSpace, startSpace, startSpace);
top.add (filler);
top.add (new JLabel ("Text"));
contentPane.addComponentListener (new ComponentAdapter ()
{
@Override
public final void componentResized (final ComponentEvent e)
{
// Just any calc based on contentPane width and height to demo problem
final int calc = (contentPane.getWidth () + contentPane.getHeight ()) / 2;
// Alter the size of the space above the label
final Dimension newSpace = new Dimension (0, calc);
filler.setMinimumSize (newSpace);
filler.setPreferredSize (newSpace);
filler.setMaximumSize (newSpace);
}
});
frame.pack ();
frame.setVisible (true);
}
}
答案 0 :(得分:1)
要回答您的问题,在更改尺寸后需要以下内容以确保调用布局管理器:
filler.revalidate();
然而,这不是一个好的解决方案,因为您解决问题的方法都是错误的。您不应该手动计算这样的组件大小。这是布局管理器的工作。所以你需要重新考虑你的布局状态。不要忘记你可以使用不同的布局管理器嵌套面板。
例如,如果您需要更改框架中的间隙,那么您应该使用BoxLayout,并且可以在开始和结束时添加“胶水”。或者您可以使用GridBagLayout,因为您可以根据可用空间控制组件的调整方式。
阅读Layout Managers上的Swing教程以获取更多信息。
答案 1 :(得分:0)
它不会让我在你的回答camickr下放一个足够长的评论:(我想补充说,发布后我也发现了这个,类似但不完全相同的问题调整BorderLayouts,他们描述了类似的北方情况/ SOUTH定位控件没有注意垂直尺寸 - Java Swing BorderLayout resize difficulties
我试过根据对它的回复来使用GridBagLayout,并且经过一些努力后确实可以使用它。基本上它是1x5网格布局,然后包含单元格(空间我强行调整大小,控制,粘合,更多控件,空间我强行调整大小),这很有用。
您不应该手动计算这样的组件大小。
我手动设置大小的唯一方法是控件上方+下方的差距,我让布局管理器处理的所有控件本身。这些间隙的大小必须与框架上的背景图像匹配,框架的大小与框架相同,但保留了纵横比,因此边框的宽度不是布局管理器可以弄清楚的,“calc”的真实代码我上面的SSCCE中的位是:
final int edge = Math.min (contentPane.getWidth () / 4, contentPane.getHeight () / 3);
final int imgHeight = edge * 3;
final int borderSize = (contentPane.getHeight () - imgHeight) / 2;
因此,如果用户将窗口调整为宽,则图像的左侧和右侧有黑色边框,borderSize = 0.如果用户将窗口调整为高,则图像上方+上方有黑色边框,而我希望控件避免去那里,所以他们总是坐在背景图像中。
但非常感谢推动正确的方向:)