如何限制 JDialog 的尺寸

Posted

技术标签:

【中文标题】如何限制 JDialog 的尺寸【英文标题】:How to limit the dimensions of a JDialog 【发布时间】:2021-04-24 22:45:02 【问题描述】:

我正在开发一个JDialog 子类(我们称之为PendenciesDialog),它向用户显示任意数量的相同大小、垂直堆叠的JPanels(最少一个)以及它们下方的关闭按钮。除了构建 JDialog 并将其打包、显示给用户并让他们关闭对话框之外,不涉及任何交互。

这些JPanels 显示了有关个人每月付款待处理的一些信息,例如帐户名称、待处理状态和付款管理系统的可点击链接。我认为我们不需要关心它们是如何构建的。

现在回答我的问题。我想将JDialog 的宽度保持在屏幕宽度的一半,并将其最大高度限制为屏幕高度的一半,或者如果挂件数量很少或只有一个,则更短。如果我无法通过调整JDialog 来实现这一点(例如,通过覆盖JDialoggetXXXSize() 方法),我可以调整它的子组件。不过我不确定我需要做什么。

为了构造JDialog,我将其布局管理器设置为BoxLayout,并使用PAGE_AXIS对齐,然后在JPanel的支持下添加JScrollPane(我们称之为JPanel的引用变量pendenciesPanel) 然后添加了一个关闭按钮。那个JPanel 也有一个BoxLayout 经理和PAGE_AXIS 对齐,并且将包含单独的挂起JPanels(实际上由于大小相等的要求,我认为它实际上应该是GridLayout)。

我打算让JScrollPane 显示pendenciesPanel 的视口,并在挂件数量太大而无法容纳JDialog(或JScrollPane)时提供滚动最大高度。

那么根据这个描述,我该如何实现JDialog的大小调整呢?从我所读到的内容看来,最合适的方法似乎是覆盖其 getXXXSize() 方法,例如:

private final Dimension SCREEN_DIMENSION = Toolkit.getDefaultToolkit().getScreenSize();

@Override
public Dimension getMaximumSize() 
    return new Dimension(SCREEN_DIMENSION.width / 2, SCREEN_DIMENSION.height / 2);

但我尝试覆盖 getMinimumSize()getPreferredSize()getSize() 等似乎不起作用,或者我可能执行错误。我需要调整其内部子组件吗?或者只是调整JDialog 就足够了?如果有,怎么做?

【问题讨论】:

我的倾向是将挂件 JPanel 放置在一个显示 JPanel 中,其 GridLayout 为一列。显示 JPanel 将放置在 JScrollPane 内。 JScrollPane 将放置在具有 BorderLayout 的主 JPanel 的中心。主 JPanel 将具有足够宽的首选尺寸,以显示悬垂 JPanel 和滚动条,高度等于 JFrame 高度的一半。 JDialog 将被打包。 @GilbertLeBlanc 您对BorderLayout 的建议实际上是我的第一次尝试,因为我最初打算在NORTH/PAGE_START 位置向对话框添加标题(该功能更改为JDialog 窗口的栏标题)和CENTER 的挂件。我也同意将尺寸基于JFrame 尺寸比基于屏幕尺寸更合适。不过,我不确定如何达到预期的大小,你的意思是我应该覆盖 JPanelgetPreferredSize() 的宽度和 getSize() 的高度? 我通常使用JPanel setPreferredSize 方法。我看不出有什么理由在这里扩展 JPanels。使用 JPanel。 我想将 JDialog 的宽度固定在屏幕宽度的一半,并将其最大高度限制为屏幕高度的一半 - 但我可以控制我的桌面。我不想让你告诉我如何使用桌面的空间。如果我想在面板中查看更多项目而不必滚动,我应该能够调整对话框的大小。 ...将覆盖它的 getXXXSize() 方法, - 是的,组件应该负责它自己的大小计算。但是,这些值只是建议。每个布局管理器可能使用也可能不使用这些尺寸。 遵守这些限制的初始大小。 - 然后覆盖或设置首选大小,而不是最大大小。 【参考方案1】:

我创建了一个简单的 GUI 来说明我的评论。这是 JFrame。

这是 JDialog。

这是完整的示例代码。您必须修改 createPendenciesPanel 方法以使其更加真实。

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.SwingUtilities;

public class JDialogTest implements Runnable 

    public static void main(String[] args) 
        SwingUtilities.invokeLater(new JDialogTest());
    

    private JFrame frame;

    @Override
    public void run() 
        frame = new JFrame("JDialog Test");
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        frame.add(createMainPanel());

        frame.pack();
        frame.setLocationByPlatform(true);
        frame.setVisible(true);
    

    private JPanel createMainPanel() 
        JPanel panel = new JPanel(new BorderLayout());
        panel.setBorder(BorderFactory.createEmptyBorder(
                150, 100, 150, 100));
        panel.setPreferredSize(new Dimension(400, 600));

        JButton button = new JButton("Open JDialog");
        button.addActionListener(new ButtonListener());
        panel.add(button);

        return panel;
    

    public class ButtonListener implements ActionListener 

        @Override
        public void actionPerformed(ActionEvent e) 
            new PendenciesDialog(frame, "Pendencies Dialog");
        

    

    public class PendenciesDialog  extends JDialog 

        private static final long serialVersionUID = 1L;

        public PendenciesDialog(JFrame frame, String title) 
            super(frame, true);
            
            setDefaultCloseOperation(DISPOSE_ON_CLOSE);
            setTitle(title);

            add(createMainPanel(frame));
            pack();
            setLocationRelativeTo(frame);
            setVisible(true);
        
        
        private JPanel createMainPanel(JFrame frame) 
            JPanel panel = new JPanel(new BorderLayout());
            
            JPanel displayPanel = createDisplayPanel();
            JScrollPane scrollPane = new JScrollPane(displayPanel);
            panel.add(scrollPane, BorderLayout.CENTER);
            
            Dimension d = frame.getSize();
            Dimension p = displayPanel.getPreferredSize();
            panel.setPreferredSize(new Dimension(p.width + 50, d.height / 2));
            
            return panel;
        
        
        private JPanel createDisplayPanel() 
            JPanel panel = new JPanel(new GridLayout(0, 1, 10, 10));
            panel.setBorder(BorderFactory.createEmptyBorder(10, 10, 10, 10));
            
            for (int i = 0; i < 6; i++) 
                panel.add(createPendenciesPanel());
            
            
            return panel;
        
        
        private JPanel createPendenciesPanel() 
            JPanel panel = new JPanel(new FlowLayout());
            panel.setBackground(Color.LIGHT_GRAY);
            panel.setPreferredSize(new Dimension(100, 200));
            
            return panel;
        

    
    

【讨论】:

感谢您的努力,尽管我没有提供简短的示例,但您很快就提出了一些代码(我认为尽管我对问题的描述允许对解决方法)。我只是被这两个重载的createMainPanel 方法弄糊涂了。我会调查你的答案。关于setPreferredSize 方法,我想我已经阅读了反对它的建议here。我不知道该怎么想。 @Piovezan:理想情况下,您不会设置首选尺寸。您可以让组件大小决定 JPanel 大小。但是,作为一个示例,绘图 JPanel 需要首选大小,因为没有组件来确定 JPanel 大小。 我建议改用 getPreferredSize ,但在这种情况下,这样做还不错,因为您正在尝试实现特定目标,因此您所做的只是限制面板大小并强制布局管理器在这些新的尺寸限制内排列组件 好的,我了解createPendenciesPanel() 方法中的setPreferredSize() 为每个悬垂面板设置最小尺寸。我不确定我是否理解createMainPanel(JFrame) 中的另一个setPreferredSize()。它正在接收一个new Dimension(int width, int height) 对象,其包含的面板宽度为+ 50(没有得到幻数,是用于滚动条吗?),高度为框架高度的一半。这对我有什么帮助?我需要宽度为框架宽度的一半,高度为包含面板的高度,上限为框架高度的一半。 @Piovezan:有两个 createMainPanel 方法,因为每个方法都属于不同的类。我设置 JPanel 首选大小的唯一两个地方是 createMainPanel (JFrame) 方法,因为只有一个 Swing 组件并且 JPanel 的大小对这个示例很重要,而 createPendenciesPanel 方法因为我创建了一个最小示例。我计算了显示 JPanel 的大小以满足您的要求。 50 覆盖了大多数 LAF 中垂直滚动条的宽度。框架高度的一半是您的要求。为什么 JDialog 应该比 pendencies JPanel 宽?

以上是关于如何限制 JDialog 的尺寸的主要内容,如果未能解决你的问题,请参考以下文章