Isaac
Isaac

Reputation: 23

Nested JSplitPane problem; setPreferredSize and setDividerLocation not working

I have a JFrame containing two JPanels, one is the menuBar and the other is the body of the frame. I desire to divide the body into three JScrollPanes such that they can be extended or reduced in size. I nested two JSplitPanes to achieve this. My problem is the setDividerLocation and the setPreferredSize that I defined for the JSplitPanes are not working. I tried resetToPreferredSizes and that too has no observable effect on the JFrame.

Here is my code:

    public class HomeView {
    private JFrame frame;
    private JPanel top;
    private JPanel center;
    private JPanel bottom;

    private JScrollPane lPane;
    private JScrollPane cPane;
    private JScrollPane rPane;

    private JSplitPane cr;
    private JSplitPane lcr;

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            public void run() {
                try {
                    HomeView window = new HomeView();
                    window.frame.setVisible(true);
                    window.cr.resetToPreferredSizes();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        });
    }

    
    public HomeView() {
        initialize();
    }

    private void initialize() {
        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        frame.setSize(Constants.pcSize);
        frame.setBackground(Color.BLACK);

        top = new JPanel();
        top.setBackground(P.light);

        center = new JPanel();
        center.setBackground(P.mix);

        bottom = new JPanel();
        bottom.setBackground(P.lightGrey);

        GroupLayout groupLayout = new GroupLayout(frame.getContentPane());
        groupLayout.setHorizontalGroup(groupLayout.createParallelGroup(Alignment.TRAILING)
                .addGroup(groupLayout.createSequentialGroup().addGap(P.Xa)
                        .addComponent(top, GroupLayout.DEFAULT_SIZE, C.mWidth, Short.MAX_VALUE).addGap(P.Xa))
                .addGroup(groupLayout.createSequentialGroup().addGap(P.Xb)
                        .addComponent(center, GroupLayout.DEFAULT_SIZE, C.pWidth, Short.MAX_VALUE).addGap(P.Xb))
                .addGroup(groupLayout.createSequentialGroup().addGap(P.Xc)
                        .addComponent(bottom, GroupLayout.DEFAULT_SIZE, C.bWidth, Short.MAX_VALUE).addGap(P.Xc)));
        groupLayout.setVerticalGroup(groupLayout.createParallelGroup(Alignment.LEADING)
                .addGroup(groupLayout.createSequentialGroup().addGap(P.H1)
                        .addComponent(top, GroupLayout.DEFAULT_SIZE, C.mHeight, Short.MAX_VALUE).addGap(P.H2)
                        .addComponent(center, GroupLayout.DEFAULT_SIZE, C.pHeight, Short.MAX_VALUE).addGap(P.H3)
                        .addComponent(bottom, GroupLayout.DEFAULT_SIZE, C.bHeight, Short.MAX_VALUE).addGap(P.HZ)));

        lPane = new JScrollPane();
        lPane.setPreferredSize(new Dimension(C.lWidth, C.lHeight));

        cPane = new JScrollPane();
        cPane.setPreferredSize(new Dimension(C.cWidth, C.cHeight));

        rPane = new JScrollPane();
        rPane.setPreferredSize(new Dimension(C.rWidth, C.rHeight));

        cr = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, cPane, rPane);
        cr.setPreferredSize(new Dimension(C.crWidth, C.crHeight));
        cr.setDividerSize(P.D);
        cr.setDividerLocation(0.8125);
        cr.setBorder(BorderFactory.createCompoundBorder());
        cr.resetToPreferredSizes();

        lcr = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, lPane, cr);
        lcr.setDividerSize(P.D);
        lcr.setDividerLocation(0.2);
        lcr.setBorder(BorderFactory.createCompoundBorder());
        lcr.resetToPreferredSizes();

        GroupLayout layoutC = new GroupLayout(center);
        layoutC.setHorizontalGroup(
                layoutC.createParallelGroup(Alignment.LEADING).addGroup(layoutC.createSequentialGroup().addGap(0)
                        .addComponent(lcr, GroupLayout.DEFAULT_SIZE, C.lcrWidth, GroupLayout.DEFAULT_SIZE).addGap(0)));
        layoutC.setVerticalGroup(layoutC.createParallelGroup(Alignment.LEADING).addGroup(layoutC.createSequentialGroup()
                .addGap(0).addComponent(lcr, GroupLayout.DEFAULT_SIZE, C.lcrHeight, GroupLayout.DEFAULT_SIZE).addGap(0)));
        center.setLayout(layoutC);

        frame.getContentPane().setLayout(groupLayout);
        frame.pack();
    }
}

my C and P classes are just storing values.

public class P {

    public static int Xa = 0;
    public static int Xb = 1;
    public static int Xc = 1;

    public static int H1 = 0;
    public static int H2 = 1;
    public static int H3 = 1;
    public static int HZ = 0;
    
    public static int D = 4;
    
    public static Color white = new Color(255, 255, 255);
    public static Color black = new Color(0, 0, 0);
    public static Color dark = new Color(60, 60, 60);
    public static Color light = new Color(220, 220, 255);
    public static Color mix = new Color(150, 180, 210);
    public static Color javaDefault = new Color(204, 204, 204);
    public static Color distinct = new Color(180, 55, 55);
    public static Color ciel = new Color(0, 55, 55);
    public static Color darkGrey = new Color(88, 88, 88);
    public static Color lightGrey = new Color(230, 230, 230);
    
}
public class C {
    public static Dimension pcSize = Toolkit.getDefaultToolkit().getScreenSize();

    private static String s = File.separator;
    public static File defaultFile = new File("metadata" + s + "default");
    public static File userFile = new File("metadata" + s + "user");

    private static int tolR = 8;
    private static int tolL = 8;
    private static int tolT = 31;
    private static int tolB = 8;

    public static int pcWidth = pcSize.width;
    public static int pcHeight = pcSize.height;

    public static int sHeight = pcHeight - tolT - tolB;
    public static int sWidth = pcWidth - tolR - tolL;

    public static int mHeight = (int) ((double) (sHeight * 0.062));
    public static int mWidth = sWidth - (2 * P.Xa);
    
    public static int bHeight = (int) ((double) (sHeight * 0.0345));
    public static int bWidth = sWidth - (2 * P.Xc);
    
    public static int pHeight = sHeight - P.H1 - mHeight - P.H2 - P.H3 - bHeight - P.HZ;
    public static int pWidth = sWidth - (2 * P.Xb);
    
    public static int lHeight = pHeight;
    public static int lWidth = (int)((double) (sWidth * 0.2));
    
    public static int cHeight = pHeight;
    public static int cWidth = (int)((double) (sWidth * 0.65));
    
    public static int rHeight = pHeight;
    public static int rWidth = sWidth - lWidth - cWidth;
    
    public static int crWidth = cWidth + rWidth;
    public static int crHeight = cHeight;
    
    public static int lcrWidth = pWidth;
    public static int lcrHeight = pHeight;
}

I just added them incase anyone wants to try run my codes.

My result:enter image description here That is not the expected prefered size or the divider location. I tried removing them and there was no change in the output. I hope someone would help me spot where things went wrong🙏. Patiently waiting.

Upvotes: 0

Views: 95

Answers (1)

camickr
camickr

Reputation: 324128

cr.setDividerLocation(0.8125);

The setDividerLocation( double ) method only works on a "realized" frame. That is components don't have a size until the layout manager has been invoked. Therefore you need to invoke pack() or setVisible(true) on the frame before invoking the setDividerLocation() method.

However, that is not really a good solution because your class is NOT designed properly. Your HomeView class should NOT know anything about the frame. It should be an independent component, Just like a JLabel, or JButton that can be added to any frame or dialog. The frame should be created in your main() method.

Then the better solution is to wrap code in a SwingUtilities.invokeLater() in the constructor of your class to add code to the end of the Event Dispatch Thread (EDT) to make sure the code executes after the frame is visible. Something like

SwingUtilities.invokeLater(new Runnable()
{
    public void run()
    {
        cr.setDividerLocation(0.8125);
    }
});

Read the Swing tuorial on How to Use Split Panes. The SplitPaneDemo code will demonstrate how to better structure your code.

Upvotes: 3

Related Questions