JDK-6409815 : REGRESSION: JSplitPane.setDividerLocation is no longer respected
  • Type: Bug
  • Component: client-libs
  • Sub-Component: javax.swing
  • Affected Version: 6
  • Priority: P3
  • Status: Closed
  • Resolution: Won't Fix
  • OS: windows_2000
  • CPU: x86
  • Submitted: 2006-04-06
  • Updated: 2010-04-02
  • Resolved: 2006-05-04
Related Reports
Relates :  
Description
A DESCRIPTION OF THE REGRESSION :
JSplitPane.setDividerLocation is no longer respected

We store the users last divider location and then use setDividerLocation to set it back to how it was when they next use the same screen.  In earlier JDKs this worked fine, in Mustang all the Split Panes are completely messed up (dividers all in the wrong places).

As a workaround we can add a component resized listener and the call setDividerLocation to move the divider to it's correct location.

  Suggested for a fix: in javax.swing.plaf.basic.BasicSplitPaneUI where it says:
if (painted) {
		// This is tricky, there is never a good time for us
		// to push the value to the splitpane, painted appears to
		// the best time to do it. What is really needed is
		// notification that layout has completed.
use spDividerLocation instead of getDividerLocation(splitPane)
(for us the spDividerLocation has the correct location).

Looking at this code it probably all needs to be fixed, hard to work out what this code is even trying to do.

 

REPRODUCIBLE TESTCASE OR STEPS TO REPRODUCE:
import static javax.swing.JFrame.*;
import static javax.swing.JSplitPane.*;
import javax.swing.*;

public class Test  {
  public static void main(String[] args) {
    SwingUtilities.invokeLater(new Runnable() {
      public void run() {
        JFrame frame = new JFrame();
        JSplitPane splitPane = new JSplitPane(HORIZONTAL_SPLIT, new JLabel("One"), new JLabel("Two"));
        splitPane.setDividerLocation(500);
        frame.add(splitPane);
        frame.pack();
        frame.setVisible(true);
        frame.setSize(1000, 1000);
        frame.setDefaultCloseOperation(EXIT_ON_CLOSE);
      }
    });
  }
}


RELEASE LAST WORKED:
5.0 Update 6

RELEASE TEST FAILS:
mustang-beta

EXPECTED VERSUS ACTUAL BEHAVIOR :
EXPECTED -
The Divider to appear in the center of the frame (at location 500 set by setDividerLocation).
ACTUAL -
The Divider appears almost at the left of the frame (so that the left label has just enough space).
Note as well as mustang-beta build 73 I also tested our application against mustang build 47 and it was broken even then.

OBSERVED APPLICATION IMPACT:
I would expect that many applications that are using setDividerLocation will end of with all their screens messed up (users will have to resize the dividers everytime they use these screens).

Comments
EVALUATION The trick to get this to happen is to change the call to setSize(1000, 1000) to a size bigger than your display size, once you do that you can see the problem. This is a regression introduced by the gray rect fix. In particular prior to this fix repaint invocations onto a frame/window/dialog/applet were handled by AWT, where as repaint invocations onto Swing components were handled by Swing. This posed a number of problems. Among them was that it was possible for Swing paints to happen before AWT paints. This test is relying on the fact that the JSPlitPane gets painted AFTER the size of the window has changed. That isn't the case in 1.6. Here's what the test does: . Frame is sized to something like 100x50 . Frame is shown . Frame is changed to size of 1000x1000 (this is not immediate, AWT may service this later). On 1.5 this results in: . layout at 100x50 . layout at 1000x1000 . paint On 1.6 it's . layout at 100x50 . paint . layout at 1000x1000 . paint It's that first paint in 1.6 that's problematic. In particular JSplitPane locks the divider location after the first paint. Since the size is smaller than 50 JSplitPane can't honor a divider location of 500 and ends up setting it to something like 25 or so. When the frame is layed out at 1000 the divider location has been locked and will not adjust. There are two possible routes to fix this: 1. Punt on the first paint event. 2. Change JSplitPane to better honor developer specified divider locations. 1 just isn't possible. This test is not representative of most apps, and there is no way we can ignore the first paint as we don't know another will be needed. There are other bugs/rfes on 2, and it's outside the scope of this bug. In addition it would likely entail compatibility issues. As there is an easy work around, and this code did not always work, I'm closing this out. I would have liked to fix this, but it just isn't possible without breaking a bunch of other things:(
04-05-2006

WORK AROUND Rather than doing: frame.pack(); // Sets size to something really small frame.setVisible(true); frame.setSize(1000, 1000); do: frame.setSize(1000, 1000); frame.setVisible(true);
04-05-2006

EVALUATION I also tried this on a windows 2000 machine in the lab and both 1.5 and 1.6 give the same behavior. Emailing submitter to see if there is a different test case I should be trying.
03-05-2006

EVALUATION The test code does the following: frame.pack(); frame.setVisible(true); frame.setSize(1000, 1000); This is problematic because pack will layout at one size, then the setSize call will layout out another size. Whether this works depends upon when the paint call is received. If paint is received before the next validate, it won't work. On the other hand if validate happens first, then paint it works. The splitpane code has not changed in a long time, what may have changed is the order of events. I've tried this on 1.5.0_06, XP, and it doesn't work there. Emailing submitter for more info.
12-04-2006