The GUI


This sample GUI does not exactly replicate the solution I submitted to Sun for the certification assignment. However, it does function in a similar manner that meets the same development requirements you'll see in the assignment instructions. There are many ways to design a GUI for the two scenarios Sun uses for the certification assignment. The GUI in this chapter is just one approach, but it scored well, so perhaps you can adapt it to your solution.

graphics/note_icon.gif

You will not be able to compile the code in this chapter's listings because it depends on other classes. The entire example is provided with the CD so that you can compile and modify that code.


First, take a look at the GUI in its entirety so that you can see how the different parts relate to one another. The code selections are presented in logical orderthe order that the flow of control is likely to follow. The GUI in Figure 13.1 shows the general structure needed to satisfy the requirements and illustrates how users can interface with the data. Note that it takes the entire code file to produce this screen.

Figure 13.1. The JTable-dominated GUI.

graphics/13fig01.gif

After you have looked over this figure, read on for a discussion of selected portions of the source code for the GUI class.

Use Explicit Imports

Avoid using the wildcard character when writing your import statements. Importing the classes individually makes the code clear, and it's easy to see what is being referenced in the body of the class. Some code listings in this book use the wildcard character to save space, but not often.

graphics/note_icon.gif

The import statements accept wildcards, but you should avoid using them, particularly when only a few classes are used in that package. Also, specify classes individually in import statements instead of using the fully-qualified name of classes in the body of your code. It is a good practice to avoid using wildcards in import statements, and I followed this practice for the certification assignment. However, compromise is needed sometimes. For example, 33 classes are imported from javax.swing package . In this case, a wildcard can make the code much more readable.


Listing 13.1 is the top of the GUI source file; it includes the file header comment, the package statement, and all the import statements. It clearly tells you what is being used in the class and hints at the functionality being built. (For example, StringTokenizer is used to parse command-line parameters.)

graphics/tip_icon.gif

Sun's evaluators review how you used SDK libraries. If you built a custom function that took a lot of work when the SDK already had a similar function, they will lower your score.


graphics/caution_icon.gif

Although you can import database classes and use local- or remote-specific code, it is better to hide from the GUI where data is coming from. The best way to make the GUI function properly is to use a connection factory. Some candidates choose to allow users to switch between local and remote modes dynamically through the GUI (by using a radio button, for example). Although this functionality is not required and is more difficult, it can earn you more points.


Listing 13.1 How to Start the GUI Source File
 /************** FILE HEADER *******************  Title:           SCJD Solution  Author:          Que Reader  Submission Date: 4/6/2004 11:58AM  Completion Date: 3/12/2004 11:58AM  Platform:        Windows 2000 ***********************************************/ package superbowl.client; /*  * The best practice for the exam is to import using  * fully-qualified names such as java.io.File  * (demonstrating that you know what you're doing) rather than  * import java.io.* (demonstrating development efficiency).  */ import superbowl.database.Database; import superbowl.database.DatabaseFactory; import superbowl.database.DatabaseException; import superbowl.database.DatabaseInterface; import java.rmi.RemoteException; import javax.swing.JTable; import javax.swing.table.DefaultTableCellRenderer; import javax.swing.table.JTableHeader; import javax.swing.border.TitledBorder; import javax.swing.table.TableModel; import javax.swing.table.TableColumnModel; import javax.swing.table.AbstractTableModel; import javax.swing.table.TableColumn; import javax.swing.JComboBox; import javax.swing.JDialog; import javax.swing.JComponent; import javax.swing.JOptionPane; import javax.swing.JTextField; import javax.swing.JFrame; import javax.swing.JPanel; import javax.swing.JScrollPane; import javax.swing.JTextPane; import javax.swing.JSplitPane; import javax.swing.JButton; import javax.swing.JLabel; import javax.swing.JMenu; import javax.swing.JMenuBar; import javax.swing.JMenuItem; import javax.swing.KeyStroke; import javax.swing.ListSelectionModel; import javax.swing.event.TableModelListener; import javax.swing.event.TableModelEvent; import javax.swing.event.ListSelectionListener; import javax.swing.event.ListSelectionEvent; import java.awt.Container; import java.awt.Component; import java.awt.BorderLayout; import java.awt.Color; import java.awt.Dimension; import java.awt.GridLayout; import java.awt.event.ActionEvent; import java.awt.event.ActionListener; import java.awt.event.WindowEvent; import java.awt.event.WindowAdapter; import java.awt.event.MouseEvent; import java.awt.event.MouseAdapter; import java.awt.event.KeyEvent; import java.awt.event.InputEvent; import java.io.IOException; import java.net.UnknownHostException; 

Listing 13.1 declares this code to be in the superbowl.client package. It also imports all the Swing components needed to build the screen shown in Figure 13.1 and imports several classes to support event handling, which happens in the View portion of the Model-View-Controller (MVC) design pattern. Last, some classes are imported to support the database and remote mode functionality.

Class Header

The class header comes after the import statements. Be sure to begin this section with a javadoc class header comment. This comment appears in the javadoc Web page, so be brief but complete.

Listing 13.2 shows the class header; it includes the javadoc comment, class declaration, and instance variables used throughout the GUI. When you design your GUI, be sure to meet all requirements mentioned in the instructions. For example, the requirements for your assignment will closely parallel the following:

  • The main data output uses a JTable.

  • The user can choose a local or remote database.

  • The user interface displays the database.

  • The user can search by level and/or aisle.

  • The user can search using "any" as a wildcard.

  • The user can reserve stadium seats.

  • The user is informed if no seats are available.

Listing 13.2 The GUI Class Header
 /**  * This user interface satisfies the following criteria:  * <ul>  * <li>Only Swing components from JFC were used.</li>  * <li>The main data output uses a JTable.</li>  * <li>The user can choose a local or remote database.</li>  * <li>The user interface displays database.</li>  * <li>The user can search by the Level and/or Aisle.</li>  * <li>The user can search by "any" as a wildcard.</li>  * <li>The user can reserve stadium seats.</li>  * <li>The user is informed if no seats are available.</li>  * </ul>  *  * The following are extra, but improve the application:  * <ul>  * <li>Display update-Table is updated after every booking and search.</li>  * <li>User messages-After every action the status is shown.</li>  * <li>Seat selection-The user selects a seat by clicking on table.</li>  * <li>User error reduction-The user cannot mistype the seat number.</li>  * <li>Color display-Level and Row columns        and search criteria colors match.</li>  * <li>The search criteria colors match the Level and Row columns.</li>  * <li>The user selects Level and Row columns from a combobox.</li>  * <li>The user selects Level and Row columns by clicking the table.</li>  * </ul>  *  * @author  Que Reader  * @version 1.00, 12/28/2003  * @since SDK1.4  */ public class SuperBowlClient extends JFrame {         boolean DISABLE = false;         boolean ENABLE = true;         private boolean ALLOW_ROW_SELECTION = true;         private int columnCount;         private DatabaseInterface database;         private DatabaseFactory databaseFactory;         private StadiumTableModel stadiumTableModel;         private TableColumn column;         private String databasePath;         private String[] columnNames,                          aisles,                          levels;         private String[][] tempData,                            data;         // GUI Swing components         private JButton searchButton,                         reserveButton;         private JSplitPane splitPane;         private JPanel reservePanel,                        reserveInputPanel,                        searchPanel,                        searchInputPanel,                        upperPanel;         private JLabel status,                        localRemote,                        searchLevel,                        searchAisle,                        seatNumberLabel,                        seatCountLabel;         private JTextField seatCount,                            seatCountField;         private JComboBox searchLevelComboBox,                           searchAisleComboBox;         private JTable table; 

Listing 13.2 includes the instance variables used by more than one method, so they had to be declared in the class scope. These instance variables provide clues for the functionality still to come.

Application Main Method

An application is always started with the main method, and where you place this method determines how you start the application. I chose the client as the natural place to put the main method, but many candidates place the main method in the connection factory. Either way is fine.

Listing 13.3 shows the main method located in the GUI class; it is abstract in design, so it will work in many similar applications. It's not specific to the certification assignment, which is the very goal of good design. Of course, object names will change in other applications, but the structure will not.

The main method accepts null arguments to connect local databases or the RMI name and port number parameters to connect a remote database. Note that any invalid command parameters will be rejected and lead to system exit. When a successful start is achieved, a client window appears on the user's screen.

Listing 13.3 Demonstrating the Main Method
 /** * Accepts null arguments to connect local database. Accepts RMI name * and port number parameters to connect a remote database. Any invalid * command parameters will be rejected * and lead to system exit. A client window will provide for each * successful connection. Default search ways are selected. * @param args the command line parameters */ public static void main( String args[] ) {     DatabaseInterface database;     DatabaseFactory databaseFactory;     try     {             // Get database from factory.             // Local is determined by "-dbpath myDBpath"             // and remote is determined by "-host myHost -port myPort"             databaseFactory = new DatabaseFactory();             database = databaseFactory.getDatabase(args);             if (database == null)             {                 System.out.println("Cannot open the database, "                                  + "please double check"                                  + " command line parameters");                 System.exit(0);             }             // initiate the client window             SuperBowlClient frame = new SuperBowlClient(database);             frame.pack();             frame.setVisible(true);     } catch ( DatabaseException de)     {         System.out.print("Unknown host, please check "                        + "command line parameters.\n" + de);     } catch (IOException io)     {         System.out.println("Cannot open the database, "                          + "please double check command"                          + " line parameters\n" + io);         System.exit(0);     } } 

The most interesting feature of Listing 13.3 is how the main method gets a connection to the database. Notice how it figures out whether the user requested a local or remote connection. Outside this method, the client is not aware of local and remote database connectivity.

An object in Java can often be considered as more than one type, determined by any interfaces the instantiating class implements. The Database concrete class implements a DatabaseInterface interface. Using this technique, you are able to specify the type as an interface that provides a generic representation of the database object. Therefore, the client can ignore the origin of the database connection, whether it's local or remote. This technique produces a clean GUI implementation. Therefore, the DatabaseInterface interface allows the client to cast references to the database by interface, not by the concrete class. That way, all code outside the main method is generic, regardless of local or remote mode. Chapters 7, "Databases and Atomicity," and 12, "Remote Method Invocation," discuss how to use one interface for RMI, which is a clean approach.

DatabaseFactory is the class that actually does the work of creating the connection and figuring out, through command-line options, whether the user requested a local or remote database connection.

Last, the main method instantiates an instance of the client by passing the database connection.

Class Constructor

The class constructor is simple. The idea is to have a concrete method that initializes the application so that another class or application can start the GUI. If all the initializing code remained in the constructor, you could still initialize the application from another object. However, I prefer using a specific method to initialize a complex application so that I can separate the class initialization from the application initialization.

Listing 13.4 shows the constructor for this class. It passes the title "Super Bowl Reservation System" to the JFrame superclass, which displays this text in the title bar. Then it calls the init method, passing the database reference. The class constructor initializes the title bar text by passing a title string to JFrame , using the super keyword. Then it assigns the database reference to the class field database . Finally, it calls the init method, which begins building the GUI.

Listing 13.4 Demonstrating the Class Constructor
 public SuperBowlClient(DatabaseInterface db) {     super("Super Bowl Reservation System");     database = db;     init(db); } 

Listing 13.4 shows how you can separate the responsibility of class initialization (that is, super() ) from that of application initialization ( init() ). This separation is not required, but it is the approach I preferred for this assignment.

Application Initialization

Now you begin the actual initialization of the application. The background work is done, including determining local or remote mode, getting a database connection, and initializing the class and instance variables. Now you build the GUI with Swing components. The primary work in this step is initializing components, adding them to containers, and then adding those containers to the window.

Listing 13.5 declares and initializes the Swing components. This is where the GUI is built. The primary work done in this method is to set up the key pieces of the visual interface, place them within their respective containers, and then display the results onscreen.

Listing 13.5 Initializing the Swing GUI
 public void init(DatabaseInterface db) {     //sanity check: make sure a reference to the     //database is not null.     if(db==null)     {         return;     }     table = new JTable();     try     {         columnNames = db.getColumnNames();         data = db.getData();     }  catch (Exception e)     {         System.out.println(e);     }     //if window closes, exit application     ApplicationExit applicationExit =   new ApplicationExit();     addWindowListener( applicationExit );     //create JTable grid     stadiumTableModel = new StadiumTableModel(data, columnNames);     table = new JTable(stadiumTableModel);     table.setPreferredScrollableViewportSize(new Dimension(800, 70));     table.setToolTipText("Click a row and Press \"Reserve Seat\" button");     table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);     if (ALLOW_ROW_SELECTION) //true by default     {         ListSelectionModel rowSM = table.getSelectionModel();         rowSM.addListSelectionListener(new ChooseSeat(rowSM) );     } else     {         table.setRowSelectionAllowed(false);     }     //Highlight columns to help user     //identify search criteria.     column = table.getColumn(table.getColumnName(1));     column.setCellRenderer(new RowRenderer());     column = table.getColumn(table.getColumnName(2));     column.setCellRenderer(new RowRenderer());     JScrollPane tableScrollPane = new JScrollPane(table);     //Create status panel for status messages     localRemote = new JLabel();     if (db instanceof Database)     {         localRemote.setText("Local Mode");     } else     {         localRemote.setText("Remote Mode");     }     localRemote.setEnabled(false);     localRemote.setHorizontalAlignment (JLabel.LEFT );     JPanel statusPanel = new JPanel();     statusPanel.setLayout (new BorderLayout());     statusPanel.setBorder(new TitledBorder("Status"));     statusPanel.setAlignmentX (JPanel.LEFT_ALIGNMENT);     status = new JLabel();     status.setHorizontalAlignment (JLabel.LEFT );     status.setEnabled(false);     status.setText("Reserving Enabled.");     statusPanel.add("West", status);     statusPanel.add("South", localRemote);     //Create search GUI feature     searchLevel = new JLabel("Level");     searchLevel.setEnabled(false);     searchLevel.setToolTipText("Select Level For Search.");     try     {       //load combo boxes with unique database values             aisles = database.getDistinctValuesForField(2);             levels = database.getDistinctValuesForField(1);     } catch(RemoteException rex)     {             System.out.print(rex);     } catch(SuperBowlException dex)     {             System.out.print(dex);     }     searchLevelComboBox = new JComboBox(levels);     searchLevelComboBox.setForeground(Color.blue);     searchLevelComboBox.setBackground(Color.white);     searchLevelComboBox.setToolTipText("Select Level For Search.");     searchLevelComboBox.setSelectedItem("any");     searchAisleComboBox = new JComboBox(aisles);     searchAisleComboBox.setToolTipText("Select Aisle For Search.");     searchAisleComboBox.setForeground(Color.red);     searchAisleComboBox.setBackground(Color.white);     searchAisle = new JLabel("Aisle");     searchAisle.setEnabled(false);     searchAisle.setToolTipText("Select Aisle For Search.");     searchButton = new JButton("Search Seats");     searchButton.setToolTipText("Search for a seat.");     searchButton.addActionListener( new SearchButtonHandler());     searchAisleComboBox.setSelectedItem("any");     int gridRows = 3;     int gridCols = 2;     searchInputPanel = new JPanel(new GridLayout(gridRows, gridCols));     searchInputPanel.add(searchLevel);     searchInputPanel.add(searchLevelComboBox);     searchInputPanel.add(searchAisle);     searchInputPanel.add(searchAisleComboBox);     searchInputPanel.add(searchButton);     searchInputPanel.setBorder(new TitledBorder("Search Seats"));     //Create reserve GUI feature     seatCount = new JTextField();     seatCountField = new JTextField();     seatNumberLabel = new JLabel("Seat number");     seatNumberLabel.setEnabled(false);     seatNumberLabel.setToolTipText("Click Seat number"                                   + " in the table at right.");     seatCount = new JTextField(10);     seatCount.setEditable(false);     seatCount.setToolTipText("Click Seat number in table at right.");     seatCountLabel = new JLabel("How Many Seats");     seatCountLabel.setEnabled(false);     seatCountLabel.setToolTipText("Enter How Many Seats"                                 + " in the blank area.");     seatCountField = new JTextField(10);     seatCountField.setToolTipText("Enter How Many Seats here.");     reserveButton = new JButton("Reserve Seat");     reserveButton.addActionListener( new ReserveButtonHandler());     reserveButton.setToolTipText("Reserve your seat.");     reserveInputPanel = new JPanel(new GridLayout(gridRows, gridCols));     reserveInputPanel.add(seatNumberLabel);     reserveInputPanel.add(seatCount);     reserveInputPanel.add(seatCountLabel);     reserveInputPanel.add(seatCountField);     reserveInputPanel.add(reserveButton);     reserveInputPanel.setBorder(new TitledBorder("Reserve Seats"));     gridRows = 1;     gridCols = 3;     upperPanel = new JPanel(new GridLayout(gridRows, gridCols));     upperPanel.add(reserveInputPanel);     upperPanel.add(searchInputPanel);     upperPanel.add(statusPanel);     //Create a split pane and put search,     //reservation, and status on top     //and JTable on bottom.     //see Sun split-pane tutorial for an excellent     //example: http://java.sun.com/docs/books/tutorial/uiswing/     //components/splitpane.html     splitPane = new JSplitPane(JSplitPane.VERTICAL_SPLIT,                                           upperPanel, tableScrollPane);     splitPane.setOneTouchExpandable(true);     splitPane.setDividerLocation(80);     //Provide minimum sizes for the two components in the split pane     upperPanel.setMinimumSize(new Dimension(100, 50));     tableScrollPane.setMinimumSize(new Dimension(100, 50));     //Add the split pane to this frame     getContentPane().add(splitPane);     //Add two top-level menu items to the GUI: File and About.     //See Listing 13.6 for the code to do this. } 

Listing 13.5 illustrates just one of the many ways you can build your GUI. This approach works fine, and you can easily modify, optimize, and adapt this code for your solution.

Figure 13.2 illustrates the tooltip text that has been added to give the user a better experience. Little touches like this make a difference on your GUI score.

Figure 13.2. An example of a tooltip, which makes the GUI easier to use.

graphics/13fig02.gif

Listing 13.5 includes the code necessary to build much of the GUI. One important aspect is adding a menu bar at the top of the window. Listing 13.6 shows how to do that and how to add menu items. In this code snippet, note that the menu bar is defined to appear at the top of the GUI window.

Listing 13.6 Adding a Menu
 /** * Adds two top-level menu items to the GUI: File and About. * You can add more if you like. */     JMenuBar menuBar = new JMenuBar();     setJMenuBar(menuBar);     // create File menu, including Open, Close, and Exit     JMenu fileMenu = new JMenu("File");     JMenuItem exitItem = new JMenuItem("Exit", 'x');     exitItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_X,                                              InputEvent.ALT_MASK));     exitItem.addActionListener(new WindowCloser());     fileMenu.add(exitItem);     menuBar.add(fileMenu);     // create Help menu and About menu item     JMenu helpMenu = new JMenu("Help");     JMenuItem helpItem = new JMenuItem("Help", 'H');     helpItem.addActionListener(new DisplayHelp());     helpMenu.add(helpItem);     JMenuItem versionItem = new JMenuItem("About", 'A');     versionItem.addActionListener(new AboutHelper());     helpMenu.add(versionItem);     menuBar.add(helpMenu); 

Listing 13.6 shows you how to add a menu to your application. This listing is rather simple, but you can easily add more menu items and give the user more menu-driven options.

Button Click Handler

The actual work of reserving a seat at the Super Bowl is done with the ReserveButtonHandler method. This method implements ActionListener , which means it is called when the Reserve button is clicked. Listing 13.7 shows you how to write this inner class and demonstrates how to respond to users clicking a button, especially the one that creates a seat reservationthe GUI's primary duty.

Listing 13.7 Demonstrating a Button Click Handler
 /** * This inner class performs the real reservation work * * Reservation Process: *    try{ *           1. Do the lock(int recnum); *           2. Do the getRow(int recnum); *           3. Do the verification to ensure the available seat; *           4. Update the record; *           5. Write the new data to screen; *           6. Do the unlock(int recordNumber); *    } * * @author Que Reader * @version 1.0  Dec-12-2004 */ public class ReserveButtonHandler implements ActionListener {     boolean DISABLE = false;     boolean ENABLE = true;     String userMessage = "Reserving your seats...Please wait";     public void actionPerformed( ActionEvent e )     {         // Check for integer, else if NumberFormatException         // then exit routine with gentle message to user.         String seats = seatCountField.getText();         int requestedSeats = 0;         int recordNumber = 0;         try         {             requestedSeats = Integer.parseInt(seats, 10);         } catch ( NumberFormatException nfe)         {             output.setText("Please provide seat count then try again.");             return;         }          if ( !(requestedSeats > 0) )         {             output.setText("Please request 1 or more seats "                          + "then try again.");             return;         }         output.setText("Reserving seats...Please wait");         // get the seat number         String seatNumber = ((JTextField)seatCount).getText();         if (seatNumber.length() == 0)         {             output.setText("Please click on a seat number "                          + "then try again.");             return;         }          try         {             rowData = database.find(seatNumber);             recordNumber = rowData.getRecordNumber();              //Lock the requested seat record             database.lock(recordNumber);              //get again because data may have changed             rowData = database.find(seatNumber);             columnData = database.getFieldInfo();              // check available seats             String values[] = rowData.getValues();             int availableSeats =                   Integer.parseInt(values[values.length-1].trim());             seats = values[values.length-1];             if (availableSeats < requestedSeats  availableSeats == 0)             {                 userMessage = "Fewer seats available than requested. "                             + "Please try again.";             } else             {                 setGUIAvailability(DISABLE, userMessage);                 // reserve seats                 availableSeats -= requestedSeats;                 values[values.length-1]= "" + availableSeats;                 database.modify(                            new RowData(recordNumber, columnData, values));                 //refresh table under previous criteria                 (new SearchButtonHandler()).searchDatabase();                 userMessage = "We have reserved " + requestedSeats                             + " seats for you on seat "                             + seatNumber + ".";              }         } catch(IOException ioe)         {   //this is thrown by lock             userMessage = "There is a problem with your Database. "                         + "Please report it to the IT staff.";             return;         } catch(DatabaseException de)         {             userMessage = "There is a problem with your Database. "                         + "Please report it to the IT staff.";             return;         } finally         {             try             {                 //Must unlock the requested seat record                 database.unlock(recordNumber);             } catch(RemoteException rex)             {                 System.out.print(rex);             } catch(DatabaseException dex)             {                 System.out.print(dex);             }             // no matter the result, restore the button status             setGUIAvailability(ENABLE, userMessage);         }     } } 

Notice that a sequence of steps is embedded in this class. One of the most important phases of the reservation process is the database integrity code. A locking mechanism prevents the data from being corrupted. This approach is not specific to the certification assignment. It is a generic procedure that includes the following steps:

  1. Lock the record with lock(int recordNumber) .

  2. Get the seat data.

  3. Verify seat availability.

  4. Update the record, if necessary.

  5. Write the new data to screen.

  6. Unlock the record with unlock(int recordNumber) .

The locking mechanism is covered in detail in Chapter 7, but these steps outline one viable way to handle database integrity in a multiuser environment.

An important aspect of the locking mechanism is that it must be managed from the client. Depending on the assignment, many candidates receive instructions that demand locking be invoked from the client. That doesn't mean this approach is the best way to implement locking. However, overlooking instructions can cause you to lose points needlessly.

Search Inner Class

Now it's time to review a database search request from the GUI. The search itself (see Chapter 7 for details) is handled by the database, but the GUI has some work to do as well.

Listing 13.8 shows you one way to handle searching the database from the GUI. The code here is simply a suggestion, but you can adapt it to your solution if you think it's useful for your project.

Notice that I used an inner class rather than a separate class. Either way is fine, but I thought the search functionality was best kept in the GUI this way.

Listing 13.8 demonstrates how this class gets the search criteria from the user, creates a search string from those criteria, invokes the search, and, finally, displays the results in a JTable, where only the rows that meet the criteria are shown.

Listing 13.8 Managing the Database Search from the GUI
 /** * This inner class implements ActionListener and * performs the database searching. */ public class SearchButtonHandler implements ActionListener {     String criteria = "",            previousCriteria = "",            levelCriteria = "",            aisleCriteria = "";     /**     * The user invokes this by clicking the Search button.     *     * @param e The ActionEvent object     */     public void actionPerformed( ActionEvent e )     {             searchDatabase();     }     /**     * This method first gets search criteria.     * Then it gives the user a status message.     * Finally, it searches the database and updates     * the GUI based on the search results.     *     */     public void searchDatabase()     {          String userMessage = "Searching the database...Please wait";         // finds the criteriaString         levelCriteria = (String)searchOriginComboBox                                 .getSelectedItem();         aisleCriteria = (String)searchDestinationComboBox                                 .getSelectedItem();         criteria =  "Level='" + levelCriteria  +"',"                  + "Aisle='" + aisleCriteria +"'";         if (!criteria.equalsIgnoreCase(previousCriteria))         {              previousCriteria = criteria;              setGUIAvailability(DISABLE, userMessage);              try              {                  tempData = database.searchSeat(criteria);              } catch(RemoteException rex)              {                  System.out.print(rex);              } catch(SuperBowlException dex)              {                  System.out.print(dex);              }              if( !(tempData==null) )              {                  stadiumTableModel =                       new StadiumTableModel(tempData, columnNames);                  setTableModelData(stadiumTableModel);                  userMessage = "Search results are in the table.";              } else              {                  //no rows met criteria                  //optional: reset grid to original data with:                  //stadiumTableModel = new StadiumTableModel(database);                  //setTableModelData(stadiumTableModel);                  userMessage = "There are no seats that match your "                              + "criteria. Please try again.";                         }                 } else                 {                         //use original because all criteria set to "any"                         stadiumTableModel =                               new StadiumTableModel(data, columnNames);                         setTableModelData(stadiumTableModel);                         userMessage = "Search results are in the table.";                 }                 setGUIAvailability(ENABLE, userMessage);                 searchLevelComboBox.setSelectedItem("any");                 searchAisleComboBox.setSelectedItem("any");      } } 

Listing 13.8 shows you how to search the database from the GUI. A surprising amount of work is done in the GUI to make this search functionality happen. The actual database search code is required, too, and is covered in Chapter 7.

Menu Handler

There is one last piece of functionality to cover. How does the GUI respond to the user clicking on a menu item? This section explains one way to provide a help Web page to the user.

Figure 13.3 shows you a partial screenshot of what the menu looks like on a Windows platform. The assignment did not require many menu items, so the GUI described in this book doesn't have many either.

Figure 13.3. A menu example.

graphics/13fig03.gif

Listing 13.9 shows you how to display a help Web page to the user with a JTextPane component. In this example, the HTML file is expected to be in the solution package, but placing the file online is a valid option, too. This inner class uses a dialog box to display the help file. Notice that a JTextPane is used to render the HTML. This control makes it easy to show help written in HTML.

Listing 13.9 Displaying User Help
 /** * This inner class displays the user help Web page. */ class DisplayHelp extends WindowAdapter implements ActionListener {     /**     * User clicked the Help menu.     * @param e The ActionEvent object     *     */     public void actionPerformed( ActionEvent e)     {         if (e.getActionCommand().equals("Help"))         {             JTextPane pane = new JTextPane();             JScrollPane scroller = new JScrollPane();             scroller.getViewport().add(pane);             JDialog dialog = new JDialog();             dialog.getContentPane().add(scroller);             dialog.pack();             dialog.setSize(800,500);             dialog.setVisible(true);             String htmlDocument = "userHelp.html";             try             {                 java.net.URL url = new java.net.URL("file:"                              + System.getProperty("user.dir")                              + System.getProperty("file.separator")                              + htmlDocument);                 pane.setPage(url);             }             catch (Exception ex)             {                 ex.printStackTrace();             }         }     } } 

Listing 13.9 shows you how to display user help when the user clicks the Help menu item. Although you can place your help file online and access it from there, I recommend submitting the file with your solution because the evaluator might want to look at the file to see how you wrote the HTML code. If you place your file online, the evaluator could still see your code by choosing View, Source from the browser menu. However, the idea is to provide everything users (including the evaluator ) need, without them needing other tools, such as a browser.



JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
JavaT 2 Developer Exam CramT 2 (Exam CX-310-252A and CX-310-027)
ISBN: N/A
EAN: N/A
Year: 2003
Pages: 187

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net