Skux
Skux

Reputation: 39

Jsplitpane automatically resizes

I have a JSPlitPane with a 50% divider between them. That works correctly.

However, when I add some JLabels to the right side, then the jsplitpane ignores my 50% divider thing and the left hand pane increases its size and just squashes the right hand side.

Why does this happen and how to fix it?

My code is:

import javax.swing.*;
import java.awt.*;

public class Example {

    private static void setup() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(500, 500));
        frame.setFocusable(true);

        JSplitPane pane= new JSplitPane();
        pane.setResizeWeight(0.5);
        pane.setRightComponent(new JPanel());

        JPanel myPanel = new JPanel();
        myPanel.setLayout(new FlowLayout());

        for(int i=0; i<20; i++) myPanel.add(new JLabel("hello"));

        pane.setLeftComponent(myPanel);

        frame.add(pane);

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

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                setup();
            }
        });
    }
}

Upvotes: 2

Views: 1739

Answers (1)

camickr
camickr

Reputation: 324128

However, when I add some JLabels to the right side, then the jsplitpane ignores my 50% divider thing and the left hand pane increases its size and just squashes the right hand side.

The split pane will initially calculate the preferred size of each component.

The resize weight is for allocating space when the split pane is resized. In this case this will happen when the frame is made visible. So if the preferred size of the components added to the split pane is less than the size of the split pane when the frame is made visible each component will get 50% of the extra space.

In the first case there are no components so the preferred size of each panel is the same, so when the split pane is resized they each get the same space.

In the second case the preferred size of the first panel will be the width of all the labels added to the panel and the second panel is 0. Since the preferred width of the first panel is greater than the size of the frame there is no extra space to allocate to the second panel.

Try adding 1 or 2 labels instead of 20 to see what happens.

Edit:

A few issue:

1) The resize weight doesn't work as you might expect. When the divider is moved as a slow speed an event is generated for every pixel. Well a pixel can't be shared by both components so the pixel is given to the right component.

I would suggest the solution in you case would be to use a resize weight of "1.0" so that the label component get all the space.

2) The JSplitPane respects the minimum size of a component which means you can't drag the bar beyond the components minimum size. For your panel the minimum size is the same as the preferred size so you won't be able to drag the divider smaller.

The solution is to override the getMinimumSize() method of the panel to return some smaller dimension

  1. Set the divider location manually to be 50% the size of the split pane when the split pane is initially displayed.

This can be done by wrapping the setDividerLocation(...) method in a SwingUtilities.invokeLater().

The above 3 suggestions have been added to your MCVE:

import javax.swing.*;
import java.awt.*;

public class Example {

    private static void setup() {
        JFrame frame = new JFrame();
        frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE);
        frame.setPreferredSize(new Dimension(500, 500));
        frame.setFocusable(true);

        JSplitPane pane= new JSplitPane();
        pane.setResizeWeight(1.0);
        pane.setRightComponent(new JPanel());

        JPanel myPanel = new JPanel()
        {
            @Override
            public Dimension getMinimumSize()
            {
                return new Dimension(50, 50);
            }
        };
        myPanel.setLayout(new FlowLayout());

        for(int i=0; i<20; i++) myPanel.add(new JLabel("hello"));

        pane.setLeftComponent(myPanel);

        frame.add(pane);

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

        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                pane.setDividerLocation(0.5f);
            }
        });
    }

    public static void main(String[] args) {
        javax.swing.SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                setup();
            }
        });
    }
}

Upvotes: 2

Related Questions