Question

I have a JFrame that contains two nested JSplitPanes. I want them to be set to an exact proportion on startup.

I can not use setDividerLocation(int) as I don't know the frame's size yet (I maximize it on startup). So, I use the proportional version, setDividerLocation(double).

Code:

// ...
JSplitPane left = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
JSplitPane right = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
right.setResizeWeight(1); // So that I can move the dividers independently
left.setLeftComponent(scrollPane1);
right.setLeftComponent(scrollPane2);
right.setRightComponent(scrollPane3);
left.setRightComponent(right);
add(left, BorderLayout.CENTER);
add(statusLabel, BorderLayout.PAGE_END);
setVisible(true);
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
left.setDividerLocation(0.3);
right.setDividerLocation(0.7);
// ...

Now, sometimes this works perfectly fine, but sometimes it doesn't change the dividers. I believe this is because the frame is not loaded on screen. From the setDividerLocation(double) docs:

If the split pane is not correctly realized and on screen, this method will have no effect (new divider location will become (current size * proportionalLocation) which is 0).

Is there a way to wait until the frame is "on screen"? This is probably about a few milliseconds, but it still breaks the layout on startup. I would not like to use Thread.sleep with a fixed value but some way that works with Swing.

EDIT: I tried the hack Behe suggested. It did not work, so it might not be about the timing.

EDIT 2: I debugged some more. It appears that this is caused by my resize weight being set to 1. However this is required by my layout.

Was it helpful?

Solution

I found a way. I added a ComponentListener to the inner JSplitPane that notifies me when it is resized by the frame maximizing. When that happens I can then safely set the resize weight.

final JSplitPane left = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
final JSplitPane right = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT);
left.setDividerLocation(0.3);
right.setDividerLocation(0.3);
left.setLeftComponent(scrollPane1);
right.setLeftComponent(scrollPane2);
right.setRightComponent(scrollPane3);
left.setRightComponent(right);
add(left, BorderLayout.CENTER);
add(status, BorderLayout.PAGE_END);
setVisible(true);
right.addComponentListener(new ComponentAdapter() {
    @Override
    public void componentResized(ComponentEvent e) {
        right.setResizeWeight(1);
    }
});
setExtendedState(getExtendedState() | JFrame.MAXIMIZED_BOTH);
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top