【问题标题】:Setting the maximum size of a JDialog?设置 JDialog 的最大大小?
【发布时间】:2011-08-11 04:12:56
【问题描述】:

简短的版本:我需要做一些棘手的事情来让 JDialog 的 setMaximumSize() 工作吗?

完整版:我有一个 JDialog(布局管理器:BorderLayout),它包含一个滚动窗格和一个底部带有提交按钮的 JPanel。

滚动窗格包含一个 JPanel,它在系统的其他地方动态构建。

我想要的是让对话框在 JPanel 周围动态调整大小到一定大小,然后开始增长滚动条。这或多或少是默认情况下发生的情况,除了最大尺寸似乎是我的显示器的尺寸。

认为这就是继承自 java.awt.Component 的 .setMaximumSize() 方法所做的,但设置它似乎没有任何效果。

设置首选大小确实会产生效果 - 但无论如何对话框总是那个大小,这真的不是我想要的。

(如果我在滚动窗格上设置最大/首选大小属性,效果是一样的。)

我是否遗漏了一些非常明显的东西?是否有一些我不知道的古怪 JDialog / BorderLayout / MaximumSize 交互?

【问题讨论】:

  • 那个“一定大小”是怎么确定的?我在下面的回答假设它由面板的内容控制。 setMaximunSize (dont-dont-dont!) 无效的原因是 BorderLayout 不遵守最大尺寸提示
  • “特定大小”基本上是“足以容纳所有内容,除非它高于屏幕高度的一半左右。”这回答了我的另一个问题:我以前从未使用过 setMaximumSize() 方法,并且对它们不起作用感到有些吃惊。但是 - 边框布局。很高兴知道。 (现在我要回去忘记它们的存在了。)

标签: java swing jdialog


【解决方案1】:

导致 JDialog 调整大小的 pack() 方法依赖于对 getPreferredSize() 的调用来确定要使用的大小。

如果你继承 JDialog,你可以通过继承这个方法来强制最大尺寸。

例子:

@Override 
public Dimension getPreferredSize() {    
  int maxWidth=500;    
  int maxHeight=300;    
  Dimension dim=super.getPreferredSize();    
  if (dim.width>maxWidth) dim.width=maxWidth;    
  if (dim.height>maxHeight) dim.height=maxHeight;    
  return dim; 
}

【讨论】:

    【解决方案2】:

    使面板实现可滚动是的方法。另请参阅(除了已经提供的教程链接 Trashgod)Rob 的博客条目

    http://tips4java.wordpress.com/2009/12/20/scrollable-panel/

    然后:

    1) 以对典型内容合理的方式实现 getPreferredScrollableViewportSize()(对于 JList f.i.,这是要显示的首选行数,即:visibleRowCount)
    2) 为那些“合理的条款”实施设置器/获取器

    该附加层(协调“合理条款”)允许所有协作组件尽最大努力提出稳健的尺寸提示,而不会像 setXXSize 那样受到不友好的干扰(这是一个no-no-never-ever,干脆忘记那些方法的存在;)

    【讨论】:

    • 啊哈!实现可滚动确实成功了。出于某种原因,我认为 setMaximumSize() 会做与 getPreferredScrollableViewportSize() 相同的事情。 (我为什么会这样想?)非常感谢!
    【解决方案3】:

    正如Sizing a Scroll Pane 中所讨论的,某些组件可以提供有关设置视口首选大小的有用信息。 JListsetVisibleRowCount() 方法特别方便,但即使getViewport().setPreferredSize(…) 也可能足够。当然,sscce 会有所帮助。

    附录:作为一个具体示例,下面的对话框最初的大小为 N-2 行。随着更多的添加,对话框会增长,直到数量达到 N。此时滚动条开始“增长”。该示例使用JList,但任何Scrollable 组件都应该是可适配的。

    import java.awt.BorderLayout;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import javax.swing.AbstractAction;
    import javax.swing.DefaultListModel;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JList;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    
    /** @see http://stackoverflow.com/questions/5759131 */
    public class ListDialog {
    
        private static final int N = 12;
        private JDialog dlg = new JDialog();
        private DefaultListModel model = new DefaultListModel();
        private JList list = new JList(model);
        private JScrollPane sp = new JScrollPane(list);
        private int count;
    
        public ListDialog() {
            JPanel panel = new JPanel();
            panel.add(new JButton(new AbstractAction("Add") {
    
                @Override
                public void actionPerformed(ActionEvent e) {
                    append();
                    if (count <= N) {
                        list.setVisibleRowCount(count);
                        dlg.pack();
                    }
                }
            }));
            for (int i = 0; i < N - 2; i++) {
                this.append();
            }
            list.setVisibleRowCount(N - 2);
            dlg.add(sp, BorderLayout.CENTER);
            dlg.add(panel, BorderLayout.SOUTH);
            dlg.pack();
            dlg.setLocationRelativeTo(null);
            dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dlg.setVisible(true);
        }
    
        private void append() {
            model.addElement("String " + String.valueOf(++count));
            list.ensureIndexIsVisible(count - 1);
        }
    
        public static void main(String[] a_args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    ListDialog pd = new ListDialog();
                }
            });
        }
    }
    

    【讨论】:

    • 一个对应的Remove按钮显示为here
    【解决方案4】:

    您必须从 JScrollPane 中的 JComponents 计算 getSize() 只是简单的示例

    编辑:并调用 JDialog#pack()

    import java.awt.BorderLayout;
    import java.awt.Dimension;
    import java.awt.EventQueue;
    import java.awt.event.ActionEvent;
    import javax.swing.JButton;
    import javax.swing.JDialog;
    import javax.swing.JPanel;
    import javax.swing.JScrollPane;
    public class PackDialog {
        private JDialog dlg;
        private JScrollPane scrollPane;
        private JPanel panel;
        private JButton btn;
    
        public PackDialog() {
            btn = new JButton();
            btn.setPreferredSize(new Dimension(300, 30));
            btn.addActionListener(new java.awt.event.ActionListener() {
    
                @Override
                public void actionPerformed(java.awt.event.ActionEvent evt) {
                    btnActionPerformed(evt);
                }
    
                private void btnActionPerformed(ActionEvent evt) {
                    int h = panel.getHeight();
                    h += btn.getHeight();
                    int w = panel.getWidth();
                    dlg.setPreferredSize(new Dimension(w, h));
                    dlg.pack();
                }
            });
            panel = new JPanel();
            panel.setPreferredSize(new Dimension(300, 600));
            panel.setLayout(new BorderLayout(10, 10));
            panel.add(btn, BorderLayout.SOUTH);
            scrollPane = new JScrollPane(panel);
            dlg = new JDialog();
            dlg.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
            dlg.setPreferredSize(new Dimension(400, 300));
            dlg.add(scrollPane);
            dlg.pack();
            dlg.setVisible(true);
        }
    
        public static void main(String[] a_args) {
            EventQueue.invokeLater(new Runnable() {
    
                @Override
                public void run() {
                    PackDialog pd = new PackDialog();
                }
            });
        }}
    

    【讨论】:

    • 我不是你的反对者,但我在这个例子中遇到了麻烦。每次按下按钮时,它似乎都会缩小对话框。
    • @trashgod 是的,输出是正确的,也许它有点加密,但我仍然认为不可能为 BorderLayout.CENTER 设置 MinSize 或 MaxSize,否则如果我将 JScrollPane 放在另一个位置/位置 NOTRH,SOUTH(等),然后输出很糟糕,从 AbsoluteLaoyut
    • 只是细节:如果我将JScrollPane 添加到TopLaoutContainer,我不需要声明一些LayoutManager,它总是占用BorderLayout.CENTER,然后是另一个JComponent(不使用任何LayoutManager) 只是 FlowLayout
    • 啊,我明白了;不知怎的,我错过了dlg.pack()
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-27
    • 2016-11-10
    • 2013-12-16
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多