Swing布局忽略水平调整大小

时间:2014-02-09 16:06:14

标签: java swing resize

我正在尝试使用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);
    }
}

2 个答案:

答案 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.如果用户将窗口调整为高,则图像上方+上方有黑色边框,而我希望控件避免去那里,所以他们总是坐在背景图像中。

但非常感谢推动正确的方向:)