简体   繁体   English

在 JDialog 上强制执行隐式最小大小?

[英]Enforcing an implicit minimum size on a JDialog?

Question问题

I have an application-modal JDialog which I want to have an enforced minimum size (ie the OS prevents the user from making the window any smaller than the minimum size).我有一个应用程序模式JDialog ,我希望它有一个强制的最小尺寸(即操作系统阻止用户使窗口小于最小尺寸)。 But the window should still be resizable (ie setResizable(false) is not an option).但是窗口应该仍然可以调整大小(即setResizable(false)不是一个选项)。 Preferably, the enforced minimum size should be implicitly defined (ie dynamically determined by the minimum sizes of the child components, and not a fixed size set explicitly using setMinimumSize )最好,强制的最小尺寸应该是隐式定义的(即由子组件的最小尺寸动态确定,而不是使用setMinimumSize显式设置的固定尺寸)

The problem I've run into is that it seems if I don't explicitly set a minimum size on the JDialog via setMinimumSize , the OS will not enforce it.我遇到的问题是,如果我没有通过setMinimumSizeJDialog上明确设置最小大小,操作系统将不会强制执行它。 So even though the JDialog implicitly knows the correct minimum size to use at any given time, that size won't be enforced unless I call something like dlg.setMinimumSize(dlg.getMinimumSize()) .因此,即使JDialog隐式地知道在任何给定时间使用的正确最小大小,除非我调用dlg.setMinimumSize(dlg.getMinimumSize())类的东西,否则不会强制执行该大小。 See the SSCCE below.请参阅下面的 SSCCE。

In many cases, explicitly setting the minimum size just before opening the dialog is sufficient.在许多情况下,在打开对话框之前明确设置最小尺寸就足够了。 However, sometimes I have a situation where the implicit minimum size can change while the dialog is open, eg a child component may be dynamically added or removed from the dialog.但是,有时我会遇到这样一种情况,即在对话框打开时隐式最小尺寸可能会发生变化,例如,可以从对话框中动态添加或删除子组件。 And if I set an explicit minimum size on the dialog, that size may not be sufficiently large for the new layout.如果我在对话框上设置了一个明确的最小尺寸,这个尺寸对于新布局来说可能不够大。

Is there any way to configure a JDialog to enforce the implicit minimum size of the dialog?有没有办法配置JDialog以强制执行对话框的隐式最小大小? If not, is there some other elegant way to enforce a dynamically changing minimum size on an open dialog?如果没有,是否有其他优雅的方法可以在打开的对话框上强制动态更改最小尺寸?

SSCCE南昌

In this SSCCE, the goal is to create a dialog that cannot be made any smaller than 300x300 pixels.在这个 SSCCE 中,目标是创建一个不能小于 300x300 像素的对话框。 This goal is only met if the minimum size is explicitly set.只有明确设置了最小尺寸才能满足此目标。

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);
    }
}

With explicit setMinimumSize call:使用显式setMinimumSize调用:

大小合适的 300x300 JDialog

Without explicit setMinimumSize call:没有明确的setMinimumSize调用:

大小不合适的 JDialog

Output in both cases:两种情况下的输出:

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

For what it's worth - I observed this on Windows 8.1 with jdk1.8.0_91.对于它的价值 - 我在带有 jdk1.8.0_91 的 Windows 8.1 上观察到了这一点。

Check comments in code.检查代码中的注释。 No magic number here!这里没有神奇的数字!

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);
    }
}

Output输出

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

However, this is less than ideal because it causes the minimum dialog size to be fixed但是,这不太理想,因为它会导致最小对话框大小被固定

Yes you should not be hardcoding values.是的,您不应该对值进行硬编码。

You could override the getMinimumSize() method of your panel to:您可以将面板的getMinimumSize()方法覆盖为:

  1. just return the prefeferred size, or只需返回首选大小,或
  2. return some ratio of the preferred size.返回一些首选大小的比例。

Edit;编辑;

is there some other elegant way to allow for a dynamically changing minimum size on an open dialog?是否有其他一些优雅的方式允许在打开的对话框中动态更改最小尺寸?

You could add an AncestorListener to your panel.您可以将AncestorListener添加到您的面板。 The ancestorAdded event is generated when the panel is added to a visible window (so basically the event is generated after the setVisible() on the dialog).当面板被添加到一个可见窗口时,就会生成ancestorAdded事件(所以基本上这个事件是在对话框上的setVisible() 之后生成的)。 Then you can use the SwingUtilities.windowForComponent(...) method to get the window for the panel.然后你可以使用SwingUtilities.windowForComponent(...)方法来获取面板的窗口。 Then you can invoked the setMinimumSize() on the dialog.然后你可以在对话框上调用 setMinimumSize() 。

I had the same issue, and that's the code i use:我有同样的问题,这就是我使用的代码:

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 ) );
        }
    }
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM