14

For a GUI application I am creating in Java, I have the following:

  • A JFrame, set to have a minimum size of (300,200)
  • A JSplitPane, in which lies:
    • On the left, a JScrollPane (containing a JTree) with a minimum size of (100,0) (I only want to restrict the width to 200)
    • On the right, a JPanel with a minimum size of (200,0)

The sizing does not give me any issue under the following conditions:

  • Resizing the JSplitPane all the way to the left (to the JScrollPane's minimum size), and subsequently resize the window afterward
  • Just resizing the window, to a certain degree

The problem occurs when I move the JSplitPane too close to the right, whereupon resizing the window the JPanel in the right of the JSplitPane fails to adhere to the minimum width I set.

I attempted setting a maximum width on the JScrollPane, which did not seem to help at all.

Is there something involving maximum sizes I must do? Or perhaps there is a way to attach a Listener to one of the panels to force my desired behavior? Ultimately, I just want the right panel in the JSplitPane to never be less than 200px wide.

Here is an example with behavior I am experiencing:

import java.awt.Dimension;
import java.awt.EventQueue;
import java.awt.GridLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JSplitPane;
import javax.swing.JTree;

public class ResizeTest
{
    private JFrame frame;
    public static void main(String[] args)
    {
        EventQueue.invokeLater(new Runnable()
        {
            public void run()
            {
                try
                {
                    ResizeTest window = new ResizeTest();
                    window.frame.setVisible(true);
                }
                catch(Exception e)
                {
                    e.printStackTrace();
                }
            }
        });
    }
    public ResizeTest()
    {
        initialize();
    }
    private void initialize()
    {
        frame = new JFrame();
        frame.setMinimumSize(new Dimension(300, 200));
        frame.setBounds(100,100,450,300);
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
        frame.getContentPane().setLayout(new GridLayout(0, 1, 0, 0));

        JSplitPane splitPane = new JSplitPane();
        frame.getContentPane().add(splitPane);

        JScrollPane scrollPane = new JScrollPane();
        scrollPane.setMinimumSize(new Dimension(100, 0));
        splitPane.setLeftComponent(scrollPane);

        JTree tree = new JTree();
        tree.setMinimumSize(new Dimension(100, 0));
        scrollPane.setViewportView(tree);

        JPanel panel = new JPanel();
        panel.setMinimumSize(new Dimension(200, 0));
        splitPane.setRightComponent(panel);
    }
}

Update:

I'm afraid I don't fully understand the point trying to be made in the proposed solutions, except for that setPreferred() and setMinimum/Maximum() are better to be avoided.

My question in response to learning this is, what are my options for restricting the JSplitPane divider outside of using these methods? MadProgrammer mentioned listening for the componentResized event, but I need just a little more clarification as to why. Am I calling setDividerLocation() in response to this event?

I apologize in advance if the appended question is meant as a separate StackOverflow question entirely, I can post another and link here if necessary.

Update 2:

Is simply not regulating how the user chooses to size the window and having the right panel in a JScrollPane a viable option? This looks to me like somewhat of a standard practice.

  • Please edit your question to include an [sscce](http://sscce.org/) that exhibits the problem you describe. – trashgod Sep 18 '12 at 23:40
  • I realize the `panel.setMinimumSize` is just for demonstration, but `tree.setMinimumSize` is a problem. [Should I avoid the use of set(Preferred|Maximum|Minimum)Size methods in Java Swing](http://stackoverflow.com/q/7229226/230513)? – trashgod Sep 19 '12 at 01:03
  • +1 for [sscce](http://sscce.org/), BTW. – trashgod Sep 19 '12 at 01:19

2 Answers2

9

Firstly, the method setMinimumSize is a suggestion to the LayoutManager API. A suggestion that may be ignored.

In order to be able to even come close to supporting this, you will need to use something like a ComponentListener and monitor the componentResized event.

The best solution I can think of is to use a LayoutManager that actually uses the minimum and maximum size constraints, something like GridBagLayout.

Use this on a "content" pane and place you're JSplitPane onto this (setting it's minimum and maximum size accordingly) then add the "content" pane to frame.

UPDATE

Sorry, I'm probably missing something really obvious, but I put this little test together, I hope it has some ideas that help :P

public class TestFrameSize extends JFrame {

    public TestFrameSize() throws HeadlessException {

        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setSize(600, 600);
        setLocationRelativeTo(null);

        setMinimumSize(new Dimension(250, 250));

        JLabel left = new JLabel("Left");
        JLabel right = new JLabel("Right");

        Dimension pSize = new Dimension(100, 100);
        Dimension mSize = new Dimension(25, 100);

        left.setPreferredSize(pSize);
        left.setMinimumSize(mSize);
        right.setPreferredSize(pSize);
        right.setMinimumSize(mSize);

        JSplitPane pane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, left, right);

        JPanel content = new JPanel(new GridBagLayout());
        content.add(pane);

        setLayout(new BorderLayout());
        add(content);

    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {

        new TestFrameSize().setVisible(true);

    }
}
MadProgrammer
  • 343,457
  • 22
  • 230
  • 366
  • `Window` inherits `set/getMinimumSize` from `Container`. While I'm pretty sure the OP wants to restrict the size of the frame as well, using `setMiniumumSize` will have not effect...am I wrong :P – MadProgrammer Sep 18 '12 at 23:43
  • Ha, you know what, `setMinimumSize` on a `JFrame` actually works :P – MadProgrammer Sep 19 '12 at 00:03
  • 1
    I'm wary of `JLabel#setPreferredSize()`. IIUC, `GridBagLayout` with default constraints acts like `GridLayout`. The text probably won't be truncated on most platforms, but it's a problem waiting to happen. – trashgod Sep 19 '12 at 01:24
  • 1
    Yep, that's a good point (it is only a demo). Personally, I hate preferred/min/max size and would to avoid if I can – MadProgrammer Sep 19 '12 at 01:37
  • At least on macOS, calling `setMinimumSize()` on the window is the _only_ way to limit the minimum size available to the user. If you want the minimum size to be computed by a layout manager, then see the solution I posted [here](https://stackoverflow.com/questions/36757982/how-do-i-set-the-minimum-size-of-a-jframe-and-get-it-to-adjust-for-frame-thickne/47321273#47321273) – Alan Snyder Nov 16 '17 at 03:57
3

In this example, the preferred size of the content of a JSplitPane is initially set to a small multiple of the component's preferred size in getPreferredSize(). Note that the JSplitPane will become no smaller than the panel's minimum size, managed by the enclosed Jlabel.

image

Community
  • 1
  • 1
trashgod
  • 203,806
  • 29
  • 246
  • 1,045
  • Your example works as expected on Mac OS X, `com.apple.laf.AquaLookAndFeel`, where the split pane's UI delegate enforces the minimum on both panes. – trashgod Sep 19 '12 at 01:07