I have a pretty big swing application and i want to make it remember sizes of all windows, jframes etc. So if user resized window how he likes, next time the window looks ex
Whatever you want to remember on the next invocation (window position, etc.) write to a file, and read that file from start up. It's going to need to be persisted to disk, nobody knows what you really want saved (probably not the time sensitive data), and any "automatic" solution can't work unless it also saves the time-sensitive data.
Would you want your application to restore with a record displayed that had been deleted? Probably not.
No, there isn't. Don't forget to write the bounds (position/size) of the main JFrame.
And after restoring window position don't forget to check if the position is really in displayed desktop area. The screen configuration may change between application runs (eg. when the user disconnects laptop from a desktop monitor).
Here's a start. The following code will find the top-most container and save the bounds of all child components to a preferences file which can then be used to restore. This probably won't handle all situations but it works for my app. Future changes can be tracked here.
public class WindowBoundsRestorer
{
private final String filename;
private Properties properties;
public WindowBoundsRestorer( String filename )
{
this.filename = filename;
}
private void setBounds( String key, Component c )
{
key = key + c.getName();
String position = properties.getProperty( key );
if ( c.getName() != null && ! StringUtils.isBlank( position ) )
{
String[] nums = position.split( "," );
c.setBounds( Integer.parseInt( nums[0] ), Integer.parseInt( nums[1] ),
Integer.parseInt( nums[2] ), Integer.parseInt( nums[3] ) );
}
if ( c instanceof Container )
{
key = key + "/";
Container container = (Container) c;
for ( Component child : container.getComponents() )
setBounds( key, child );
}
}
/**
* Loads the properties from the .xml file and sets all named windows with a matching
* name.
*
* @param component Any component in the Swing app. The top-most container will be
* determined from this component.
*/
public void restore( Component component )
{
properties = new Properties();
InputStream is = null;
try
{
is = new FileInputStream( filename );
properties.loadFromXML( is );
}
catch ( IOException e )
{
e.printStackTrace();
return;
}
finally
{
IOUtils.closeQuietly( is );
}
Component top = component;
while ( top.getParent() != null )
top = top.getParent();
setBounds( "", top );
}
private void getBounds( String key, Component c )
{
key = key + c.getName();
String position = String.format( "%d,%d,%d,%d", c.getX(), c.getY(), c.getWidth(), c.getHeight() );
properties.setProperty( key, position );
if ( c instanceof Container )
{
key = key + "/";
Container container = (Container) c;
for ( Component child : container.getComponents() )
getBounds( key, child );
}
}
public void save( Component component )
{
Component top = component;
while ( top.getParent() != null )
top = top.getParent();
properties = new Properties();
getBounds( "", top );
OutputStream os = null;
try
{
os = new FileOutputStream( filename );
properties.storeToXML( os, "Browser" );
}
catch ( IOException e )
{
e.printStackTrace();
}
finally
{
IOUtils.closeQuietly( os );
}
}
}
Is there a better option than to write the position/size of each window in
Preferences
?
No, there isn't. Don't forget to write the bounds (position/size) of the main JFrame
. You could write the parameters to an XML file instead of a preferences file, but that's an implementation detail.
Is there any convenient way to store the order of columns in a
JTable
?
Write the column names and positions out to your preferences file.
While this task is common, the implementation of this task is dependent on what you want to save from your GUI.
The way I would save these GUI parameters would be to create a model class that contains all of the bounds and other parameters that you're interested in saving. I would read a XML file that contains these parameters and populate the fields in the model class. If there's no file, I'd set defaults.
The GUI would use the fields in the model class to build the GUI. As the user modifies the GUI, I'd update the model class with the new values.
When the user closes the GUI, I'd write out the model class to an XML file.
I prefer using XML files over properties files because it's easier to see the structure of the model, and I find XML files easier to modify when the GUI changes.
I've always used java.util.Preferences
for this, but a javax.jnlp.PersistenceService works "even for applications that are running in the restricted execution environment."