Setting the maximum size of a JDialog?

14,666

Solution 1

Make the panel imlement Scrollable is the way to go. See also (in addition to the tutorial link Trashgod already provided) Rob's blog entry

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

then:

1) implement getPreferredScrollableViewportSize() in terms reasonable for the typical content (for a JList f.i. that's the preferred number of rows to show, aka: visibleRowCount)
2) implement setters/getters for those "reasonable terms"

That additional layer (coordiates "reasonable terms") allows all collaborating components to do their best to come up with robust size hints without unfriendly interference as setXXSize (which is a no-no-never-ever, simply forget those methods exist ;)

Solution 2

As discussed in Sizing a Scroll Pane, some components can provide useful information about setting the viewport's preferred size. The setVisibleRowCount() method of JList is particularly convenient, but even getViewport().setPreferredSize(…) may suffice. Naturally, an sscce would help.

Addendum: As a concrete example, the dialog below is initially sized to have N-2 rows. As more are added, the dialog grows until the number reaches N. At that point the scrollbars start "growing". The example uses a JList, but any Scrollable component should be adaptable.

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

Solution 3

The pack() method which causes the JDialog to be sized relies on a call to getPreferredSize() to determine which size to use.

If you subclass JDialog you can enforce a maximum size by subclassing this method.

Example:

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

Solution 4

you have to calculate getSize() from JComponents inside JScrollPane just simple example

Edit: and call 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();
            }
        });
    }}
Share:
14,666
Dave
Author by

Dave

Lifelong computer enthusiast turned Software developer. Recently emerged from the command-line C world into web systems under .NET. I'm greatly enjoying the fact I haven't had a single pointer-related error in over a year.

Updated on June 09, 2022

Comments

  • Dave
    Dave almost 2 years

    The short version: do I need to do something tricky to get JDialog's setMaximumSize() to work?

    The full version: I've got a JDialog (layout manager: BorderLayout) which contains a scroll pane and a JPanel on the bottom with the commit buttons.

    The scroll pane contains a JPanel which is built dynamically elsewhere in the system.

    What I want is for the dialog to dynamically size itself around the JPanel up to a certain size, and then start growing scrollbars. This is, more or less, what happens by default, except the maximum size seems to be the size of my monitor.

    I thought this is what the .setMaximumSize() method inherited from java.awt.Component did, but setting it doesn't seem to have any effect.

    Setting the preferred size does has an effect - but then the dialog is always that size no matter what, which really isn't what I want.

    (And the effects are the same if I set the maximum/preferred size properties on the scroll pane.)

    Have I missed something tremendously obvious? Is there some wacky JDialog / BorderLayout / MaximumSize interaction I don't know about?

  • trashgod
    trashgod about 13 years
    I'm not your down-voter, but I'm having trouble with this example. It appears to shrink the dialog each time the button is pressed.
  • mKorbel
    mKorbel about 13 years
    @ trashgod yes that's correct outPut, maybe it's little bit crypted, but I still think that's not possible to set MinSize or MaxSize for BorderLayout.CENTER, otherwise sure it works if I placed JScrollPane to the another possitions/place NOTRH, SOUTH (etc), then output is terrible as from AbsoluteLaoyut
  • mKorbel
    mKorbel about 13 years
    just details: I don't need to declare some LayoutManager if I'll add JScrollPane to the TopLaoutContainer, it's always occupated BorderLayout.CENTER, then for another JComponent (without usage of any LayoutManager) is only FlowLayout
  • trashgod
    trashgod about 13 years
    Ah, I see now; somehow I missed the dlg.pack().
  • Dave
    Dave about 13 years
    AHA! Implementing scrollable did the trick exactly. For some reason, I thought setMaximumSize() would do the same thing as getPreferredScrollableViewportSize(). (Why would I think that?) Thank you very much!
  • trashgod
    trashgod almost 12 years
    A corresponding Remove button is shown here.