Setting divider location on a JSplitPane doesn't work
Asked Answered
F

4

15

I'm trying to set the divider location of a JSplitPane but it seems not to work.

Here's an SSCCE:

import java.awt.Color;
import javax.swing.BoxLayout;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JSplitPane;


public class JSplitProblem extends JFrame {

    public JSplitProblem(){
        JPanel upperPanel = new JPanel();
        upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));

        JPanel leftPanel = new JPanel();

        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
        JPanel red = new JPanel();
        red.setBackground(Color.red);
        leftPanel.add(red);

        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
        JPanel blue = new JPanel();
        blue.setBackground(Color.blue);
        rightPanel.add(blue);

        upperPanel.add(leftPanel);
        upperPanel.add(rightPanel);
        JPanel bottomPanel = new JPanel();
        bottomPanel.setBackground(Color.black);

        JSplitPane mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel,bottomPanel);
        mainSplittedPane.setOneTouchExpandable(true);
        mainSplittedPane.setDividerLocation(0.5);

        this.add(mainSplittedPane);
        this.setSize(800,600);
        this.setResizable(true);
        this.setVisible(true);
    }

    public static void main(String[] args) {
        new JSplitProblem();
    }

}

I would like the black bottom panel to lay on a 50% of the whole area by default. What am I doing wrong?

Flaring answered 2/10, 2011 at 10:12 Comment(2)
IIRC setDividerLocation with a ratio works only AFTER the splitpane has been made visible in a containment hierarchy. That's probably because the method immediately calculates the actual location in pixels, based on the current size.Tabaret
@jfpoilpret: yes. I understood that from mKorbel's answer. Otherwise using invoke later won't effect it. Thanks for pointing out anyway.Flaring
C
10

nothing complicated in this case, with rules

1) PrefferedSize must returns Childs not as I wrong to set in my case too :-), then my answer isn't @kleopatra resist too

2) put everything about rezize, size, whatever for JSplitPane into invokeLater() .

enter image description here .

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

public class JSplitProblem extends JFrame {

    private static final long serialVersionUID = 1L;
    private JSplitPane mainSplittedPane;

    public JSplitProblem() {
        JPanel upperPanel = new JPanel();
        upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
        JPanel red = new JPanel();
        red.setBackground(Color.red);
        leftPanel.add(red);
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
        JPanel blue = new JPanel();
        blue.setBackground(Color.blue);
        rightPanel.add(blue);
        upperPanel.add(leftPanel);
        upperPanel.add(rightPanel);
        JPanel bottomPanel = new JPanel();
        bottomPanel.setBackground(Color.black);

        mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel, bottomPanel);
        mainSplittedPane.setOneTouchExpandable(true);
        mainSplittedPane.setDividerLocation(0.5);

        add(mainSplittedPane);
        setPreferredSize(new Dimension(400, 300));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(true);
        setVisible(true);
        pack();
        restoreDefaults();
    }

    private void restoreDefaults() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().height /2);
                //mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().width /2);
            }
        });
    }

    public static void main(String[] args) {
        JSplitProblem jSplitProblem = new JSplitProblem();
    }
}
Chemosmosis answered 2/10, 2011 at 10:30 Comment(4)
oh..thanks for the answer but I still got some problem (and I have been a bit imprecise while asking the question). The point is, your solution works only if I don't resize the frame. If I manually resize the frame proportion isn't mantained. Is there a way to keep the diveder location always at a certain value? +1 anywayFlaring
yes very simple, you have to add WindowListener, override proper ResizeEvent(s), but notice calling the restoreDefaults() to delay that with java.swing.Timer, because you never ever don't know is resize ends, becasue if resize continue, then just to restart the Timer :-)Chemosmosis
+1 the key is that the setDividerLocation(double) only works on a visible GUI since it can't calculate the size ratio until the split pane actually has a size. In the simple example there is no need to use invokeLater. Just invoke the setDividerLocation(...) method after the pack(), setVisible(true). If you want to use the restoreDefaults() method then you should invoke it when you create the splitpane.Recrudescence
Could you please clarify what this means: "PrefferedSize must returns Childs not as I wrong to set in my case too :-), then my answer isn't @kleopatra resist too"Checkbook
R
17

If you want both halves of the split pane to share in the split pane's extra or removed space, set the resize weight to 0.5: (Tutorial)

JSplitPane mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel,bottomPanel);
mainSplittedPane.setOneTouchExpandable(true);
mainSplittedPane.setResizeWeight(0.5);                            
Relinquish answered 2/10, 2011 at 10:27 Comment(1)
+1: thanks for setResizeWeight. I'll play with it a little bit and see what I can do.Flaring
C
10

nothing complicated in this case, with rules

1) PrefferedSize must returns Childs not as I wrong to set in my case too :-), then my answer isn't @kleopatra resist too

2) put everything about rezize, size, whatever for JSplitPane into invokeLater() .

enter image description here .

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

public class JSplitProblem extends JFrame {

    private static final long serialVersionUID = 1L;
    private JSplitPane mainSplittedPane;

    public JSplitProblem() {
        JPanel upperPanel = new JPanel();
        upperPanel.setLayout(new BoxLayout(upperPanel, BoxLayout.X_AXIS));
        JPanel leftPanel = new JPanel();
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
        JPanel red = new JPanel();
        red.setBackground(Color.red);
        leftPanel.add(red);
        JPanel rightPanel = new JPanel();
        rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
        JPanel blue = new JPanel();
        blue.setBackground(Color.blue);
        rightPanel.add(blue);
        upperPanel.add(leftPanel);
        upperPanel.add(rightPanel);
        JPanel bottomPanel = new JPanel();
        bottomPanel.setBackground(Color.black);

        mainSplittedPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT, upperPanel, bottomPanel);
        mainSplittedPane.setOneTouchExpandable(true);
        mainSplittedPane.setDividerLocation(0.5);

        add(mainSplittedPane);
        setPreferredSize(new Dimension(400, 300));
        setDefaultCloseOperation(EXIT_ON_CLOSE);
        setResizable(true);
        setVisible(true);
        pack();
        restoreDefaults();
    }

    private void restoreDefaults() {
        SwingUtilities.invokeLater(new Runnable() {

            @Override
            public void run() {
                mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().height /2);
                //mainSplittedPane.setDividerLocation(mainSplittedPane.getSize().width /2);
            }
        });
    }

    public static void main(String[] args) {
        JSplitProblem jSplitProblem = new JSplitProblem();
    }
}
Chemosmosis answered 2/10, 2011 at 10:30 Comment(4)
oh..thanks for the answer but I still got some problem (and I have been a bit imprecise while asking the question). The point is, your solution works only if I don't resize the frame. If I manually resize the frame proportion isn't mantained. Is there a way to keep the diveder location always at a certain value? +1 anywayFlaring
yes very simple, you have to add WindowListener, override proper ResizeEvent(s), but notice calling the restoreDefaults() to delay that with java.swing.Timer, because you never ever don't know is resize ends, becasue if resize continue, then just to restart the Timer :-)Chemosmosis
+1 the key is that the setDividerLocation(double) only works on a visible GUI since it can't calculate the size ratio until the split pane actually has a size. In the simple example there is no need to use invokeLater. Just invoke the setDividerLocation(...) method after the pack(), setVisible(true). If you want to use the restoreDefaults() method then you should invoke it when you create the splitpane.Recrudescence
Could you please clarify what this means: "PrefferedSize must returns Childs not as I wrong to set in my case too :-), then my answer isn't @kleopatra resist too"Checkbook
O
3

I'm not sure, but I think you should try to pack() your frame. And if that doesn't work, try to reset the divider location after you packed the frame.

Operose answered 2/10, 2011 at 10:20 Comment(0)
T
1

Just add the code below, and that will be fairly enough.

mainSplittedPane.setResizeWeight(0.5);
Traceytrachea answered 14/4, 2014 at 6:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.