Search code examples
javamultithreadingswingawtinvokelater

How to set divider location for JSplitPane on start-up


I have JPanel which contains JSplitPane. The JPanel is injected during a runtime into a JFrame using the method invokeAndWait. Then the invokeLater is called to update divider location in SplitPane.
The problem is, when the divider update is invoked, JPanel width is still 0.
When I add sleep or a breakpoint anywhere in the code (except the invokeLater), the code works fine.

    final JPanel viewPanel = new JPanel();
    viewPanel.setLayout(new BorderLayout());

    final JPanel header = getPresenterHeader(getPageTitle(), getPageInstructions());
    viewPanel.add(header, BorderLayout.NORTH);
    viewPanel.add(getSplitPane(), BorderLayout.CENTER);

    toolbar = createActionsToolBar();
    toolbar.addAction(new ExitPresenterAction(this));
    viewPanel.add(toolbar, BorderLayout.SOUTH);    
    addContent(viewPanel);

    SwingUtilities.invokeLater(new Runnable()
    {
        @Override
        public void run()
        {
            splitPane.setDividerLocation(0.5);
        }
    }); 

Solution

  • I'm not sure whether it helps for you, but we have a method which mostly helps in this situation:

    public static JSplitPane setDividerLocation(final JSplitPane splitter, final double proportion) {
        if (splitter.isShowing()) {
            if ((splitter.getWidth() > 0) && (splitter.getHeight() > 0)) {
                splitter.setDividerLocation(proportion);
            } else {
                splitter.addComponentListener(new ComponentAdapter() {
                    @Override
                    public void componentResized(ComponentEvent ce) {
                        splitter.removeComponentListener(this);
                        setDividerLocation(splitter, proportion);
                    }
                });
            }
        } else {
            splitter.addHierarchyListener(new HierarchyListener() {
                @Override
                public void hierarchyChanged(HierarchyEvent e) {
                    if (((e.getChangeFlags() & HierarchyEvent.SHOWING_CHANGED) != 0) && splitter.isShowing()) {
                        splitter.removeHierarchyListener(this);
                        setDividerLocation(splitter, proportion);
                    }
                }
            });
        }
        return splitter;
    }
    

    Use it instead of invokeLater call

    setDividerLocation(splitPane, 0.5);