Roll Your Own Swing-based XML Editor (Part III)

Editor’s note: This is the third and final part of a series about how to build your own XML editor.

f you’ve been looking for a cross-platform, open-source, XML editor, you’ve likely come up short. In this three-part series of articles I will walk you through the development of a simple, no frills, XML editor, utilizing several of the most common Java 2 Swing components. This series will be beneficial to anyone wanting to write their own XML editor, or just to those of you looking to learn or brush up on Swing.

This is the third article in the series. In the first article, we briefly discussed XML and why a tree structure is appropriate to display XML, how to handle XML data, how to work with the JTree Swing component, and we built a reusable component that is capable of parsing an XML document and displaying its data in a JTree.

In the second article, we created the framework for our XML editor. In order to do so, we covered a variety of Swing components (including JSplitPane, JScrollPane, JButton, and JTextArea). The JSplitPane object contained two JScrollPane objects, one to house the graphical view of the XML, the other to house the textual view.

In this final article, we will add the finishing touches to our XML editor to make it more user-friendly. We will start by building a menu system, then move on to constructing JFileChooser components to access the underlying file system to allow XML documents to be saved and new documents to be opened. Finally, we will use a JDialog box to allow the user to cancel a command to exit the application.



How can I enhance my Swing applications so that they utilize menus, access the file system, and allow users to cancel actions?



Create JMenu components to handle the application’s menus, JFileChooser components to access the underlying file system, and use a JDialog box to allow users to cancel actions.

Overview:

  • Build the menu components
  • Handle the menu events
  • Build the file system access components
  • Build the dialog component to verify choices
  • Conclusion

    In the previous article, we developed the XTree class, a reusable component derived from the JTree class and capable of displaying XML data as a graphical tree. Because of our keen use of object-oriented principles, none of the changes we will make today will require us to touch that class. It is a self-contained reusable class that is used by, but not coupled with our JFrame container.

  • Build the Menu Components
    A JMenu component consists of several objects: a menu bar, one or more menus, and one or menu items. The menu bar contains menus, which in turn contain the menu items. The Swing component names for each of these are quite intuitive (JMenuBar, JMenu, and JMenuItem, respectively).

    Below is the entire code required to create a minimal “File” menu containing a single menu item:

    JMenu fileMenu = new JMenu( “File” );	JmenuItem exitItem = new JMenuItem( “Exit” );	fileMenu.add( exitItem );		JmenuBar menuBar = new JMenuBar();	menuBar.add( fileMenu );	setJMenuBar( menuBar );

    This process should seem very familiar. A JMenu component is built, as any other Java GUI component is built. The innermost elements are added to their immediate parents, until all elements have defined an appropriate container.

    Returning to the XmlEditor case study, we have actually created a more complete file menu with the ability to create a new XML document, open an existing document, save a document, and exit. We’ll learn more about that in the next section.

    Handle the Menu Events
    Let’s say that we want to create a typical file menu, allowing our users to create a new document, open an existing document, save the current document, and exit the application. Now that we know how to build the menu itself, how do we go about responding to the user’s menu selection? As with other Swing components, the answer lies within the event model and listener components that are made available.

    The most basic way to handle a menu selection is the add an action listener to a menu item: exitItem.addActionListener( new exitMenuHandler() ); When dealing with complex event handling(as menu systems tend to become complex), it is considered good practice to define event handlers as separate classes. The example given above is adding an action listener of type exitMenuHandler. This type will be defined later in the application. Below is a minimal definition for an exitMenuHandler class:

    class exitMenuHandler implements ActionListener { public void actionPerformed( ActionEvent ae ) {	System.exit(0); }} 

    While this implemention might seem too simplistic to warrant a separate class definition, when we define the event handling code for opening and saving documents, you will recognize the value in separating this functionality into a separate class file. Additionally, this approach would allow you to reuse common menu functionality between different applications.

    Build the File System Access Components
    There is often a need for your Java Swing applications to allow the user to access the file system through a graphical file system browser. Typically, this is a result of the user wanting to open or save a component or file. In our XmlEditor application, we want users to be able to do exactly that.

    To access the underlying file system, the javax.swing package has an excellent component, the JFileChooser component. No doubt, you have used a Swing application before that utilized the JFileChooser component.

    To create a JFileChooser, you first instantiate a JFileChooser object, set its size, and then declare it to either open files, or save them. To do this, you associate the object with its parent – the object that will invoke it (a menu item in our case) – and then set it to be either an open dialog or save dialog. To do this, you use the showSaveDialog() or showOpenDialog(), both of which have a return type of int. Below is a brief example:

    JFileChooser jfc = new JFileChooser();jfc.setSize( 500, 250 );Container parent = openItem.getParent();int choice = jfc.showOpenDialog(parent);

    The integer that is returned in the final line indicates whether or not the user ultimately opens/saves a file, or presses the cancel button. To respond to the open/save event, the integer can be compared to the APPROVE_OPTION constant defined in the JFileChooser class. At this point, you simply use whatever means are appropriate for you to open/save/serialize the request file on behalf of the user.

    To see a complete implementation of this, consult Listing 1; it contains all six methods used to construct the menu handling functionality for the XmlEditor application.

    Build the Dialog Component to Verify Choices
    Currently, whenever you click the Jframe’s close window, the application immediately closes down. This is not good. What if the user accidentally closes the window in the middle of working on a file? We want to prompt the user and ask them if it is all right to shut the application down.

    To do that, we want to use a JDialog box. Dialog boxes are used by every graphical application that is worth their salt. They will prompt the user before writing over another file, closing an open file without saving it, or before closing an application. We will only concern ourselves with closing the editor.

    What we need to do is create a JDialog box complete with a Jlabel containing the prompt, and two buttons, one to accept the closing of the program, the other to reject it. Below is the code to construct this component:

    	JDialog verifyDialog = new JDialog( this, “Confirm Exit”, true );	Jlabel question = new JLabel( “Are you sure you want to exit?” );		Jbutton okButton = new JButton( “OK” );	okButton.addActionListener( this );	Jbutton cancelButton = new JButton( “Cancel” );	cancelButton.addActionListener( this );	verifyDialog.getContentPane().setLayout( new FlowLayout() );	verifyDialog.getContentPane().add( question );	verifyDialog.getContentPane().add( okButton );	verifyDialog.getContentPane().add( cancelButton );	verifyDialog.hide();

    Now, only two things remain. We must write the event handling code for the two buttons, and override the window closing event behavior. As far as handling the two buttons, we simply want to close the application when ‘OK’ is pressed, and hide the dialog box when ‘Cancel’ is pressed.

    The final step is to override the default window closing event behavior. By default, even if you create a dialog box and the user clicks the cancel button, the JFrame has still received the “close window ” event. This will cause the JFrame to hide itself unless we override it with the following setting:

    setDefaultCloseOperation( JFrame.DO_NOTHING_ON_CLOSE ); 

    The above line belongs in the constructor when the other properties of the frame are defined. This new setting will make it so that the JFrame never closes itself in response to a window close event. It will only close itself in response to a System.exit() call.

    Congratulations!
    A lot of material has been covered in this last installment. An entire article could easily have been written on the JMenu component, JFileChooser, and JDialog components. I encourage you to download the source code and study the changes made between the last version and this new version.

    Once you’ve added the menu component, defined event handling routines for the menu events, and added a means of canceling an accidental window close event, they you are ready to test the application and begin to create, edit, and save XML files!

    Congratulations! You have a home-grown, Swing-based, XML Editor. Play around with it, make it more robust, and tell me what you come up with. I’d love to hear from you!

    Share the Post:
    Share on facebook
    Share on twitter
    Share on linkedin

    Overview

    Recent Articles: