Skip to content

Instantly share code, notes, and snippets.

@daveray
Created June 12, 2011 21:05
Show Gist options
  • Save daveray/1021984 to your computer and use it in GitHub Desktop.
Save daveray/1021984 to your computer and use it in GitHub Desktop.
Workaround JSplitPane.setDividerLocation without resorting to sub-classing and other abominations.
import java.awt.event.ComponentAdapter;
import java.awt.event.ComponentEvent;
import java.awt.event.HierarchyEvent;
import java.awt.event.HierarchyListener;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JSplitPane;
import javax.swing.SwingUtilities;
public class JSplitPainInTheAss {
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;
}
public static void main(String[] args) {
SwingUtilities.invokeLater(new Runnable() {
@Override
public void run() {
final JFrame frame = new JFrame("JSplitPainInTheAss");
final JSplitPane splitter = new JSplitPane(JSplitPane.VERTICAL_SPLIT, new JLabel("TOP"), new JLabel("BOTTOM"));
setDividerLocation(splitter, 0.75);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setContentPane(splitter);
frame.setSize(800, 600);
frame.setVisible(true);
}});
}
}
@daveray
Copy link
Author

daveray commented Jun 13, 2011

Actually, it turns out that a HierarchyChangeListener is notified when the splitter becomes displayable. That combined with a temporary component resize listener seems to also work without having to worry about spamming the UI thread with a lot of invokeLaters. I'll experiment some more and update as needed.

@grkuntzmd
Copy link

Cool! I'll have to see if that works for the JTextComponent subclasses. Check this out.

@daveray
Copy link
Author

daveray commented Jun 13, 2011

Yep. That works. In my larger test case, it doesn't work with the single event handler. In my case, the split pane is created one the fly and inserted dynamically into an already visible pane. In this case, the showing-changed event happens before the split pane is laid out in its parent so width and height are still zero. I have to listen for the following resize before setting the divider location. It's progress though :)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment