【问题标题】:Making sure SpringLayout doesn't shrink below a certain size确保 SpringLayout 不会缩小到特定大小以下
【发布时间】:2012-01-03 22:07:37
【问题描述】:

我正在尝试使用 SpringLayout 实现一个非常简单的 UI(部分原因是我,与我在网上找到的大多数教程作者相反,与其他布局管理器相比,它的编码界面非常相似,部分原因是我想要学习如何使用它)。 UI 基本上是这样的:

这一切都很好。如果我增加窗口大小,UI 会按照我想要的方式调整大小(保持欢迎文本居中并扩展文本区域以填充所有新的可用空间)。但是,在某个点以下(更具体地说,当窗口对于欢迎文本变得太窄时):

我希望窗口不允许进一步缩小,这样如果用户试图将窗口缩小到小于足以容纳组件的大小,它就会停止。如何使用SpringLayout 布局管理器完成此操作?

我知道我可以通过处理一些调整大小事件并检查是否达到最小尺寸来做到这一点,然后将尺寸设置为最小尺寸。但这需要我 a) 知道或知道如何计算窗口的最小尺寸,甚至在它呈现之前,b) 编写一堆事件处理代码只是为了让一些 UI 呈现正确,并且 c) 编写一个一堆我希望一个好的布局管理器处理的代码;)

【问题讨论】:

    标签: java swing springlayout


    【解决方案1】:
    1. 您可以将MinimumSize 覆盖为TopLevelContainer

    2. 您已将JTextArea 放入JScrollPane

    3. 最简单的方法是混合LayoutManagers(称为NestedLayout),通过将GUI 拆分为各个部分(将JPanels 与相同或不同的LayoutManager 分开),而不是实现一些最复杂的LayoutManagerGridBagLayoutSpringLayout) 为整个 Container

    4. 一些LayoutManagers相当忽略setXxxSize

    5. SpringLayout 不是我的 Java 杯

    import java.awt.*;
    import javax.swing.*;
    
    public class MinSizeForContainer {
    
        private JFrame frame = new JFrame("some frame title");
    
        public MinSizeForContainer() {
            JTextArea textArea = new JTextArea(15, 30);
            JScrollPane scrollPane = new JScrollPane(textArea);
    
            CustomJPanel fatherPanel = new CustomJPanel();
            fatherPanel.setLayout(new SpringLayout());
    
            frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
            frame.add(fatherPanel, BorderLayout.CENTER);
            frame.setLocation(20, 20);
            frame.setMinimumSize(fatherPanel.getMinimumSize());
            frame.pack();
            frame.setVisible(true);
        }
    
        public static void main(String[] args) {
            SwingUtilities.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    MinSizeForContainer Mpgp = new MinSizeForContainer();
                }
            });
        }
    }
    
    class CustomJPanel extends JPanel {
    
        private static final long serialVersionUID = 1L;
    
        @Override
        public Dimension getMinimumSize() {
            return new Dimension(400, 400);
        }
    }
    

    【讨论】:

    • 看,这里的问题是最小尺寸最终是硬编码的。我想完全避免这种情况,所以我以后可以决定添加另一个 UI 元素(例如,右侧的一个长而窄的列表),而不必在我的代码中重写任何内容。
    • +1 TextLayout,显示为here,是一种获得最小界限的方法,但经过验证的首选尺寸也应该不错。
    • getXXSize 中的硬编码大小几乎与使用 setXXSize 一样糟糕;-)
    • 忘记了:+1 用于检测 window.setMinimumSize 的大小保证(在操作系统允许的范围内)合同 - 直到昨天才知道 :-)
    • @kleopatra 一种课程(@Andrew Thompson)
    【解决方案2】:

    要实现“真实”(不可缩小)最小尺寸有几个问题:

    • 子组件必须返回一些合理的(基于它们的内容)最小尺寸,许多核心组件不这样做
    • layoutManager 必须尊重所有子项的复合最小值,无论可用空间多么小
    • 顶级容器(此处为 JFrame)不得缩小超出最小值

    第一个对于 JLabel 是正确的,第二个对于 SpringLayout 是正确的(这就是标签被截断的原因) - 这将第三个作为潜在问题,解决方案并不明显,实际上我不知道在运行@mKorbel 的示例之前,它甚至是可能的。相关行确实是

    frame.setMinimumSize(someSize);
    

    有了这条线,就不可能缩小下面的框架。没有,它是。从那个观察开始,一些挖掘结果证明了 Window 中覆盖的文档

    将此窗口的最小尺寸设置为一个常数值。 [..] 如果 当前窗口的大小小于 minimumSize 窗口的大小 会自动放大以符合最小尺寸。如果 setSize 或 之后调用 setBounds 方法,其宽度或高度小于 [...] 会自动放大以符合 minimumSize 值。 如果用户尝试调整大小,调整大小操作可能会受到限制 窗口低于 minimumSize 值。此行为取决于平台。

    看代码,有两个(实现,不要依赖它们:-)与最小尺寸相关的细节

     Dimension minSize;
     boolean minSizeSet;
    

    和公共api访问

     public Dimension getMinimumSize()
     public boolean isMininumSizeSet()
    

    第一个相当旧(jdk1.1),后者相当新(jdk1.5) - 暗示第一个不能依赖后者,但在内部必须检查 null minSize。 Window 上覆盖的大小调整方法(保证尽最大努力尊重手动设置的 minSize)是最新的(jdk6),do 依赖于后者。或者换句话说:覆盖 isMinimumSizeSet 就可以了。

    一些代码 sn-p(注意:这是一个 hack,未经测试,很可能是依赖于操作系统的,具有不良副作用!):

        // JFrame.setDefaultLookAndFeelDecorated(true);
        JFrame frame = new JFrame("some frame title") {
    
            /**
             * Overridden to tricks sizing to respect the min.
             */
            @Override
            public boolean isMinimumSizeSet() {
                return true; //super.isMinimumSizeSet();
            }
    
            /**
             * Overridden to adjust for insets if tricksing and not using 
             * LAF decorations.
             */
            @Override
            public Dimension getMinimumSize() {
                Dimension dim = super.getMinimumSize();
                // adjust for insets if we are faking the isMinSet
                if (!super.isMinimumSizeSet() && !isDefaultLookAndFeelDecorated()) {
                   Insets insets = getInsets();
                   dim.width += insets.left + insets.right;
                   dim.height += insets.bottom + insets.top;
                }
                return dim;
            }
    
    
    
        };
        // add a component which reports a content-related min
        JLabel label = new JLabel("Welcome to my application!");
        // make it a big min
        label.setFont(label.getFont().deriveFont(40f));
        frame.add(label); 
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.pack();
        frame.setVisible(true);
    

    【讨论】:

    • bump +1 我投票给了如此不同且有价值的答案,难以置信,请继续保持与您的答案相同的韧性水平
    猜你喜欢
    • 1970-01-01
    • 2020-08-24
    • 2013-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-06-24
    • 1970-01-01
    • 2017-03-31
    相关资源
    最近更新 更多