// Grades.java - Written by Wayne Pollock, Tampa Florida USA, 5/2001. // This swing applet uses JDBC to retrieve a student's grades from // an ODBC database. Since DB access may be slow by an applet, // the DB access is done in a seperate thread so the GUI is still // fast and responsive. This applet also uses doc comments that // could be processed by javadoc (but probably won't be). // Grades is both an Applet and a stand-alone program, however as // an Applet it will need extra permissions to access ODBC. // // Adapted from a sample program "OutputApplet.java" from "JDBC API // Tutorial and Reference", 2nd Ed., by White, Fisher, et. al., // (C) Sun Microsystems 1999. A pretty good book! import java.applet.*; import java.awt.*; import java.awt.event.*; import java.util.*; import java.sql.*; import javax.swing.*; import javax.swing.table.*; /** * This JDBC swing applet reads a student ID and PIN, * and displays that student's grades from the Grades ODBC database. * @author Wayne Pollock * @version 1.0 * @See * Book info, errata, and code */ public class Grades extends JApplet implements ActionListener, Runnable { // Note: Private fields almost never have doc comments. private Thread worker; private PreparedStatement stmt; private Connection con; private String DB = "Grades"; // to do: Set these from PARAM tags. private String DBDriver = "sun.jdbc.odbc.JdbcOdbcDriver"; private String password = ""; // Better to use a servlet, private String userName = ""; // so no passwords are given out. private JButton submit; private JTextField studentID; private JPasswordField PIN; private JComponent comp; // Holds the JTable *or* a JLabel message. private JPanel display; // Holds a JTable created from resultSet. private JLabel status, message; public void init () { // Create required objects: submit = new JButton( "Submit" ); submit.setEnabled( false ); // Disable until connection to DB is made. studentID = new JTextField( 12 ); PIN = new JPasswordField( 4 ); display = new JPanel(new BorderLayout() ); status = new JLabel( "" ); message = new JLabel( "", JLabel.CENTER ); message.setForeground( Color.black ); message.setFont( new Font( "Serif", Font.BOLD, 18 ) ); JLabel idlbl = new JLabel( "Student ID: " ); idlbl.setLabelFor( studentID ); idlbl.setDisplayedMnemonic( 'S' ); JLabel pinlbl = new JLabel( "PIN: " ); pinlbl.setLabelFor( PIN ); pinlbl.setDisplayedMnemonic( 'P' ); JLabel title = new JLabel( "View Your Grades", JLabel.CENTER ); title.setFont( new Font( "SansSerif", Font.BOLD, 24 ) ); title.setForeground( Color.blue.darker() ); // Create GUI Layout: Container c = getContentPane(); c.setLayout( new BorderLayout() ); JPanel top = new JPanel( new BorderLayout() ); top.add( title, "North" ); top.add( new JLabel(" "), "Center" ); // Just a spacer. Box inputBox = Box.createHorizontalBox(); inputBox.add( Box.createHorizontalGlue() ); inputBox.add( idlbl ); inputBox.add( studentID ); inputBox.add( Box.createHorizontalStrut( 8 ) ); inputBox.add( pinlbl ); inputBox.add( PIN ); inputBox.add( Box.createHorizontalStrut( 8 ) ); inputBox.add( submit ); inputBox.add( Box.createHorizontalGlue() ); top.add( inputBox, "South" ); c.add( top, "North" ); c.add( new JLabel( " " ) ); // Just a spacer. display.add( status, "South" ); c.add( display, "South" ); showMsg( "Enter your ID and PIN and then click \"Submit\"" ); // Setup Event Handling: studentID.requestFocus(); submit.addActionListener( this ); getRootPane().setDefaultButton( submit ); PIN.setNextFocusableComponent( studentID ); // Load driver: setStatus( "Loading Database Driver..." ); try { Class.forName( DBDriver ); } catch ( Exception ex ) { showMsg( "Can't find Database driver class:
" + ex + "" ); setStatus( "Database Driver Not Loaded." ); submit.setEnabled( false ); } setStatus( "Database Driver loaded." ); } /** This method is invoked each time the use visits the web page * containing this applet. */ public void start () { final String url = "jdbc:odbc:" + DB; final String query = "select * from Grades where " + "Student_ID = ? and PIN = ?"; // To allow GUI to be active right away, the DB connection // is done in a background thread, using an anonymous inner // Runnable class: Thread t = new Thread( new Runnable () { public void run () { try { setStatus( "Connecting to Database..." ); con = DriverManager.getConnection( url, userName, password ); stmt = con.prepareStatement( query ); submit.setEnabled( true ); setStatus( "Connected to Database, ready for Query..." ); } catch ( SQLException ex ) { showMsg( "" + "SQLException:
" + "" + ex + "" ); setStatus( "Failed to Connect to the Database." ); submit.setEnabled( false ); } } } ); t.start(); } public void stop () { try { setStatus( "Disconnecting from Database..." ); submit.setEnabled( false ); if ( stmt != null ) stmt.close(); if ( con != null ) con.close(); setStatus( "Disconnected from Database." ); } catch ( SQLException ex ) { showMsg( "" + "SQLException:
" + "" + ex + "" ); setStatus( "Failed to close Database Connection." ); submit.setEnabled( false ); } } public void actionPerformed (ActionEvent ae ) { Thread t = new Thread( this ); t.start(); studentID.requestFocus(); } public void run () { String table[][], headers[]; setStatus( "Retrieving Data, please wait..." ); // Set the values in the prepared statement from textFields: try { String id = studentID.getText().trim(); String pin = new String( PIN.getPassword() ).trim(); stmt.setString( 1, id ); stmt.setString( 2, pin ); ResultSet rs = stmt.executeQuery(); // Collect meta-data: ResultSetMetaData meta = rs.getMetaData(); int numColumns = meta.getColumnCount(); // Create array of column headers. // Note we display all fields except "PIN": headers = new String[ numColumns - 1 ]; for ( int i = 1, h = 0; i <= numColumns; ++i ) { String colName = meta.getColumnLabel( i ); if ( ! colName.equalsIgnoreCase( "PIN" ) ) { headers[h] = colName; ++h; } } // Create 2-D array of row data. Note in this application // it is an error if there is more (or less) than one row: int rowCount = 0; table = new String[1][headers.length]; while ( rs.next() ) { for ( int i = 0; i < headers.length; ++i ) { String data = rs.getString( headers[i] ); table[0][i] = data; } ++rowCount; } if ( rowCount != 1 ) { showMsg( "" + "Invalid ID or PIN!
(row count = " + rowCount + ")" ); setStatus( "Connected to Database, ready for Query..." ); return; } } catch ( SQLException ex ) { showMsg( "" + "SQLException:
" + "" + ex + "" ); setStatus( "Connected to Database, ready for Query..." ); return; } // Create and display JTable. This JTable uses a default Table model, // which doesn't resize columns automatically for a best fit, and // allows cells to be edited. (It would be better to create a // custom data model with the desired features. Maybe next time.): JTable jt = new JTable( table, headers ); jt.setPreferredScrollableViewportSize( new Dimension( getSize().width, 2 * jt.getRowHeight() ) ); jt.setRowSelectionAllowed( true ); display.remove( comp ); comp = new JScrollPane( jt ); display.add( comp, "Center" ); setStatus( "Connected to Database, ready for Query..." ); validate(); } /** Replaces the component in the middle of the applet with a * JLabel showing the requested message. Note the component * currently showing is either a JLable or a JScrollPane. */ protected void showMsg ( String msg ) { if ( comp != null ) display.remove( comp ); if ( msg == null ) message.setText( "" ); else message.setText( msg ); comp = message; display.add( comp, "Center" ); setStatus( null ); } /** Updates the status line at the bottom of the display JPanel. */ protected void setStatus ( String msg ) { if ( msg == null ) status.setText( "" ); else status.setText( msg ); } public static void main ( String [] args ) { JFrame f = new JFrame( "Grades JDBC Swing program" ); f.setSize( 680, 200 ); // Center the JFrame on the screen: Toolkit tk = Toolkit.getDefaultToolkit(); int screenWidth = tk.getScreenSize().width; int screenHeight = tk.getScreenSize().height; int frameWidth = f.getSize().width; int frameHeight = f.getSize().height; f.setLocation( ( screenWidth - frameWidth ) / 2, ( screenHeight - frameHeight ) / 2 ); // Add window closing handler: f.addWindowListener( new WindowAdapter () { public void windowClosing ( WindowEvent we ) { System.exit( 0 ); } } ); Grades g = new Grades(); f.getContentPane().add( g, "Center" ); f.show(); g.init(); g.start(); } }
Send comments and mail to the WebMaster. |