1

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);
        }
    }); 
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48
Jakub Čech
  • 49
  • 1
  • 7
  • It shouldn't, `invokeLater` will be deferred if called in EDT. – grape_mao Oct 24 '16 at 08:41
  • Yes, I can't get my head around it. As I understand `invokeLater`, it should wait for GUI to be expanded. – Jakub Čech Oct 24 '16 at 08:45
  • 1
    Be sure to build your Swing GUI objects on the [event dispatch thread](http://docs.oracle.com/javase/tutorial/uiswing/concurrency/initial.html) _before_ you post another event, for [example](http://stackoverflow.com/a/5071109/230513). – trashgod Oct 24 '16 at 09:07
  • I've changed the title for your question. The new title can probably help for other developers to find this solution. – Sergiy Medvynskyy Oct 24 '16 at 11:33

1 Answers1

3

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);
Sergiy Medvynskyy
  • 11,160
  • 1
  • 32
  • 48