-
-
Save daveray/1021984 to your computer and use it in GitHub Desktop.
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); | |
}}); | |
} | |
} |
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.
Cool! I'll have to see if that works for the JTextComponent subclasses. Check this out.
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 :)
I've just started testing it on a much much larger example. As in all Swing workaround, I've already had to add some additional hacks (the width and height checks) :)
It appears to retry twice in this larger system, but I could imagine a case where it ends up spinning if the splitpane is created but not displayed soon. It seems to cover the common case so far though. I'll keep updating this gist as I learn more...