【问题标题】:Enforcing an implicit minimum size on a JDialog?在 JDialog 上强制执行隐式最小大小?
【发布时间】:2017-03-01 16:05:19
【问题描述】:

问题

我有一个应用程序模式JDialog,我希望它具有强制的最小尺寸(即操作系统阻止用户使窗口小于最小尺寸)。但窗口仍应可调整大小(即setResizable(false) 不是一个选项)。最好是隐式定义强制的最小尺寸(即由子组件的最小尺寸动态确定,而不是使用setMinimumSize 明确设置的固定尺寸)

我遇到的问题是,如果我没有通过setMinimumSize 明确设置JDialog 的最小大小,操作系统将不会强制执行它。因此,即使JDialog 隐含地知道在任何给定时间使用的正确最小大小,除非我调用类似dlg.setMinimumSize(dlg.getMinimumSize()) 的东西,否则不会强制执行该大小。请参阅下面的 SSCCE。

在许多情况下,在打开对话框之前明确设置最小尺寸就足够了。但是,有时我会遇到这样一种情况,即在打开对话框时隐式最小大小可能会发生变化,例如可以从对话框中动态添加或删除子组件。如果我在对话框上设置了一个明确的最小尺寸,那么这个尺寸对于新布局来说可能不够大。

有什么方法可以配置JDialog 来强制执行对话框的隐式最小大小?如果没有,是否有其他优雅的方法可以在打开的对话框上强制动态更改最小大小?

SSCCE

在此 SSCCE 中,目标是创建一个不能小于 300x300 像素的对话框。只有明确设置了最小大小,才能实现此目标。

public class SSCCE {
    public static void main(String[] args) {
        JDialog dlg = new JDialog(null, ModalityType.APPLICATION_MODAL);
        dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(new JLabel("300x300"), BorderLayout.CENTER);

        // The panel is given a hard-coded minimum size just to make the
        // problem easier to see
        pnl.setMinimumSize(new Dimension(300,300));

        dlg.add(pnl);

        System.out.println("Dialog minimum size: " + dlg.getMinimumSize());
        // Minimum size is not enforced by the OS without this call
        dlg.setMinimumSize(dlg.getMinimumSize());
        System.out.println("Dialog minimum size: " + dlg.getMinimumSize());

        dlg.pack();
        dlg.setVisible(true);
    }
}

使用明确的setMinimumSize 调用:

没有明确的setMinimumSize 调用:

两种情况下的输出:

对话框最小尺寸:java.awt.Dimension[width=300,height=300]
对话框最小尺寸:java.awt.Dimension[width=300,height=300]

对于它的价值 - 我在带有 jdk1.8.0_91 的 Windows 8.1 上观察到这一点。

【问题讨论】:

  • “一个不能小于 300x300 像素的对话框。” 为什么?更重要的是,为什么是对话框,而不是对话框的内容区域(面板)?
  • @AndrewThompson 为 SSCCE 任意选择 300x300 尺寸。在 SSCCE 中,我手动将其设置为 JPanel 的最小尺寸,以模拟一些具有固有最小尺寸的控件或容器,如 JLabel 或 JTable。最小尺寸通过布局管理器向上传播 - 因为面板的最小尺寸为 300x300,所以对话框的最小尺寸也应为 300x300。但操作系统不会强制执行此操作,除非我通过调用 JDialog.setMinimumSize() 明确设置最小大小。

标签: java swing awt jdialog


【解决方案1】:

检查代码中的 cmets。这里没有幻数!

import java.awt.*;
import java.awt.Dialog.ModalityType;
import javax.swing.*;

public class SSCCE {
    public static void main(String[] args) {
        JDialog dlg = new JDialog(null, ModalityType.APPLICATION_MODAL);
        dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);

        JPanel pnl = new JPanel(new BorderLayout());
        pnl.add(new JLabel("As big as needed"), BorderLayout.CENTER);
        //pnl.setMinimumSize(new Dimension(300,300));
        dlg.add(pnl);

        System.out.println("Dialog minimum size: " + dlg.getMinimumSize());
        dlg.pack(); // make the dialog as large as needed to display content
        // Minimum size is not enforced by the OS without this call
        dlg.setMinimumSize(dlg.getPreferredSize());
        System.out.println("Dialog minimum size: " + dlg.getMinimumSize());

        dlg.setVisible(true);
    }
}

输出

Dialog minimum size: java.awt.Dimension[width=97,height=16]
Dialog minimum size: java.awt.Dimension[width=113,height=55]

【讨论】:

  • 嗨 Andrew,正如我也向 camickr 提到的那样,JPanel 上的硬编码最小尺寸只是为了在 SSCCE 中保持简洁。我的实际问题是关于如何让操作系统强制执行JDialog 的隐式最小大小。我更新了我的问题以使其更清楚。
【解决方案2】:

但是,这并不理想,因为它会导致固定最小对话框大小

是的,您不应该对值进行硬编码。

您可以覆盖面板的getMinimumSize() 方法:

  1. 只返回首选尺寸,或者
  2. 返回首选大小的某个比例。

编辑;

是否有其他优雅的方式允许在打开的对话框上动态更改最小尺寸?

您可以在面板中添加AncestorListenerancestorAdded 事件是在面板添加到可见窗口时生成的(所以基本上该事件是在对话框上的 setVisible() 之后生成的)。然后您可以使用SwingUtilities.windowForComponent(...) 方法获取面板的窗口。然后您可以在对话框中调用 setMinimumSize()。

【讨论】:

  • 我已经尝试在JPanel 上覆盖getMinimumSize(),它没有任何区别。硬编码值只是为了在 SSCCE 中简洁。 JDialog 知道正确的最小尺寸,问题是除非通过 dlg.setMinimumSize(...) 明确设置,否则它不会强制执行它。
  • 这很有帮助,谢谢。我想我也可以使用ContainerListener 来响应添加/删除组件。
【解决方案3】:

我遇到了同样的问题,这就是我使用的代码:

addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        Dimension size = getSize();
        
        if( size.getWidth() <= getMinimumSize().getWidth() || size.getHeight() <= getMinimumSize().getHeight() ) {
            int width = (int) (getMinimumSize().getWidth() + 2);
            int height = (int) (getMinimumSize().getHeight() + 2);
            
            setSize( new Dimension( width, height ) );
        }
    }
});

【讨论】:

    猜你喜欢
    • 2017-05-12
    • 2018-03-06
    • 2011-08-11
    • 2011-02-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-02-07
    相关资源
    最近更新 更多