I have a JFrame with a JSplitPane that is OneTouchExpandable. I want to remember the last Divider position of the JSplitPane on JFrame dispose and restore the Position if the JFrame is reopened.
It works well, but if the User expand one Side via the oneTouchExpandable UI-Widget then I store only the 'int'-Position on dispose and set the 'int'-Position back again with the consequence on JFrame-resizing the JSplitPane-Divider jumps to the collapsed Component preferredSize.
How can I get/set the collapse/expand State?
EDIT
Now: the resize-Behavior is OK, but it is not exactly the same behavior like the first-time-open - cause now I have no MinimumDividerLocation. I wanted the SnapIn but further the collapsedState.
public class SplitPaneState {
public static void main( String[] args ) {
SwingUtilities.invokeLater( new Runnable() {
@Override
public void run() {
new SplitPaneState().createAndSowGUI();
}
});
}
private int position = -1;
private Dimension size = new Dimension( 500, 300 );
private void createAndSowGUI() {
final JFrame frame = new JFrame("frame");
frame.setSize( 200, 100 );
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
frame.setLocationRelativeTo( null );
frame.getContentPane().add( new JButton( new AbstractAction(){
{
putValue( Action.NAME, "Open Dialog" );
}
@Override
public void actionPerformed( ActionEvent e ) {
final JSplitPane splitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT, new JLabel( "left Component" ), new JLabel( "right Component" ));
splitPane.setContinuousLayout( true );
splitPane.setOneTouchExpandable( true );
if(position != -1) {
boolean LeftIsCollapsed = position < splitPane.getMinimumDividerLocation();
if(LeftIsCollapsed) {
splitPane.getLeftComponent().setMinimumSize(new Dimension()); // fix by Martijn Courteaux
splitPane.setDividerLocation(0.0d); // fix by Martijn Courteaux
}else {
splitPane.setDividerLocation(position);
}
}
JDialog dialog = new JDialog(frame,"dialog"){
@Override
public void dispose() {
position = splitPane.getDividerLocation();
size = this.getSize();
super.dispose();
}
};
dialog.setSize( size );
dialog.setDefaultCloseOperation( JFrame.DISPOSE_ON_CLOSE );
dialog.setLocationRelativeTo( frame );
dialog.getContentPane().add( splitPane );
dialog.setVisible( true );
}
}
));
frame.setVisible( true );
}
}
http://docs.oracle.com/javase/7/docs/api/javax/swing/JSplitPane.html
So basically you need to have created your whole UI, called .pack() on the main JFrame AND after that you can use JSplitPane.setDividerLocation(double). If you do it before UI layouting and all that stuff is done, the method will just do nothing as it states in the documentation and you already experienced.
JSplitPane has a method setDividerLocation(double), which sets the divider location as a percentage of the JSplitPane's size. I tried to create similar functionality some time ago. I had the same problem. But even when I use the setDividerLocation(double) method, it didn't work properly. I believe that it's just JSplitPane bug.
Forcing the divider position to a very small/large value to hide the top/bottom component works, but is defeated when the split pane gets resized, because of the component minimum size. Setting that size to 0 (as proposed in the accepted answer) works, but there are cases when you cannot/don't want to override that.
After looking into the
BasicSplitPaneUI
and associated classes, it turns out the "one touch expanding" buttons are callingBasicSPlitPaneUI.setKeepHidden(true)
, so the divider will stick to either end when resized.Unfortunately, that method is package-private but setting the associated
keepHidden
field can be done using introspection, as shown in another answer:Is hiding your dialog/frame an option?
I found that it is possible to collapse one side of the splitpane by setting the minimum size of the component to
new Dimension()
and then set the divider location:You can play with these settings to store and restore the collapse/expand state.