Ricebridge
Search This Site
Feb 07 2012 23:13 UTC

Got a question for us?
Just Ask!


$15 Gift Certificate for every bug you find.

Bookmark Ricebridge Java Components - user friendly and well documented at del.icio.us Digg Ricebridge Java Components - user friendly and well documented at Digg.com Bookmark Ricebridge Java Components - user friendly and well documented at reddit.com Bookmark Ricebridge Java Components - user friendly and well documented at YahooMyWeb Bookmark Ricebridge Java Components - user friendly and well documented at Spurl.net Bookmark Ricebridge Java Components - user friendly and well documented at Simpy.com Bookmark Polyphasic Mutants at NewsVine Blink this Ricebridge Java Components - user friendly and well documented at blinklist.com Bookmark Ricebridge Java Components - user friendly and well documented at Furl.net Fark Ricebridge Java Components - user friendly and well documented at Fark.com

Swing Table Example

Summary

This is a simple Swing example showing you how to:

  • load data records from XML and display them in a table
  • allow the user to edit the data and save it back out to an XML file

The Data

We will use a small XML file as the example data. This file contains the details of several plays by a randomly chosen playwright from the West Midlands.

plays.xml

<plays>
<author name="Shakespeare">
<play type="COMEDY" year="1595"><title>A Midsummer Night's Dream</title></play>
<play type="COMEDY" year="1602"><title>All's Well That Ends Well</title></play>
...
<play type="COMEDY" year="1594"><title>Two Gentlemen of Verona</title></play>
</author>
</plays>

We want to display this data as a table for the user to edit. We'll provide a set of default XPath expressions to get the user started, and put them in text fields so the user can edit them. We'll also let the user cut-and-paste the data into a spreadsheet. Here's a small screenshot:

The default expressions are

  • To get each play: /plays/author/play
  • To get the author (using an absolute path): /plays/author/@name
  • To get the play title (relative to the product): title
  • To get the play year (relative to the product): @year
  • To get the play type (relative to the product): @type

Defining the User Interface

We'll just use some standard Swing code for this example. Some extracts are shown below to give you an overview of the structure of the application. Review the SwingTable.java source code to see the exact details.


public SwingTable() throws Exception {
  ...

  iMainFrame   = new JFrame("SwingTable");
  iMainFrame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

  Box toolbox = new Box( BoxLayout.Y_AXIS );
  toolbox.add( makeLoadBar() );
  toolbox.add( makeSpecBar() );

  makeTable();

  iMainFrame.getContentPane().add( toolbox, BorderLayout.NORTH);
  iMainFrame.getContentPane().add( ts,      BorderLayout.CENTER);
}


public void makeTable() {
  iTable = new JTable();

  ActionMap am = iTable.getActionMap();
  am.put( "selectall", new AbstractAction() {
      public void actionPerformed( ActionEvent pEvent ) {        
        iTable.selectAll();
      }
    });
  ... 

  KeyStroke selectall = KeyStroke.getKeyStroke(KeyEvent.VK_A,ActionEvent.CTRL_MASK,false);
  ...

  InputMap im = iTable.getInputMap();
  im.put( selectall, "selectall");
  ...
}


public JToolBar makeLoadBar() {
  JToolBar toolbar = new JToolBar();
  new BoxLayout( toolbar, BoxLayout.X_AXIS );
  ...

  JButton loadB = new JButton( "Load XML File" );
  ...

  loadB.addActionListener( new AbstractAction() {
      public void actionPerformed( ActionEvent e ) {
        try {
          File xmlFile = askForXmlFile( true );
          if( null != xmlFile ) {
            load( xmlFile );
          }
        }
        catch( XmlManagerException xme ) {
          displayError( xme.getUserMessage() );
        }
      }
    } );
    ...

    toolbar.add( loadB );
    ... 

    return toolbar;
}


public JToolBar makeSpecBar() {
  iSpecBar = new JToolBar();    

  JLabel rl = new JLabel("Record:");
  iSpecBar.add( rl );
  iRecordPath = new JTextField("/plays/author/play");
  iSpecBar.add( iRecordPath );
  ...

  String[] fieldpath = new String[] { "/plays/author/@name", "title", "@year", "@type" };
  for( int fI = 0; fI < fieldpath.length; fI++ ) {  
    addField( fieldpath[fI] );
  }

  return iSpecBar;
}

...

Loading the Data

When the user hits the Load XML File button, we ask them for an XML file using a JFileChooser dialog, and then we parse it using XML Manager. We then construct a RecordSpec using the values in the text fields, and use that to load the data into a Swing TableModel. The actual loading of the data takes one line of code:

TableModel tm  = iXmlManager.loadTableModel( pXmlFile, rs );

Here is the code of the load method, and the makeRecordSpec utility method. You can see that after loading the data, we update the user interface. If there is an error, we display the user-friendly error message that XML Manager provides.


private void load( File pXmlFile ) {
  boolean enablebuttons = false;
  try {
    RecordSpec rs = makeRecordSpec();
    TableModel tm  = iXmlManager.loadTableModel( pXmlFile, rs );
    iTable.setModel( tm );
    iTable.requestFocusInWindow();
    iXmlFile = pXmlFile;
    iMainFrame.setTitle( iXmlFile.getName() );
    enablebuttons = true;
  }
  catch( XmlManagerException xme ) {
    displayError( xme.getUserMessage() );
  }
  finally {
    iReloadButton.setEnabled( enablebuttons );
  }
}

private RecordSpec makeRecordSpec() {
  String[] fieldpaths = new String[ iFieldPaths.size() ]; 
  for( int fI = 0; fI < fieldpaths.length; fI++ ) {
    fieldpaths[fI] = ((JTextField)iFieldPaths.get(fI)).getText();
  }
  RecordSpec rs = new RecordSpec( iRecordPath.getText(), fieldpaths ); 
  return rs;
}

Saving the Data

We've made the table editable, so the user can click on a table cell and alter the text in the cell. When the user clicks on the Save XML File button, we pop up another JFileChooser dialog, and ask them where they want to save the modified data. We then use the current XPath expressions to create a new XML file. Read the FIX RecordSpec documentation to get more details on using XPath for creating XML files. Here is the code that saves the data:


private void save( File pXmlFile ) {
  boolean enablebuttons = false;
  try {
    RecordSpec rs = makeRecordSpec();
    TableModel tm = iTable.getModel();
    iXmlManager.saveTableModel( pXmlFile, rs, tm );
    iXmlFile = pXmlFile;
    iMainFrame.setTitle( iXmlFile.getName() );
  }
  catch( XmlManagerException xme ) {
    displayError( xme.getUserMessage() );
  }
}

Additional Features

Run the SwingTable application to try out the additional features. You can copy-and-paste the entire table into a spreadsheet using the Copy Table button. You can also select a smaller area of the table and copy-and-paste the data in that rectangle using the Ctrl-C and Ctrl-V key commands.

The View XML File button lets you take a look at the XML source of the file you are loading or saving. This can be useful for working out the exact XPath expressions that you need.

Finally, you can see the RecordSpec source code using the Show RecordSpec button.

The full source code of SwingTable.java is also available.

Questions and Comments

Please feel free to email us at examples@ricebridge.com if you have any questions or comments about this example.

comment on this page Home | Search | About Us | Contact Us | Our Products | Documentation | Resources | Login
Copyright © 2004-2012 Ricebridge. All Rights Reserved.