Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Professional Java.JDK.5.Edition (Wrox)

.pdf
Скачиваний:
31
Добавлен:
29.02.2016
Размер:
12.07 Mб
Скачать

Chapter 4

try { Class.forName(“org.gjt.mm.mysql.Driver”); Connection conn =

DriverManager.getConnection(“jdbc:mysql://localhost/annotationtest”,

“”, “”);

PreparedStatement preparedStmt =

conn.prepareStatement(“SELECT * FROM PERSON WHERE FILENAME = ?”); preparedStmt.setString( 1, filename.toString());

ResultSet result = preparedStmt.executeQuery(); ArrayList list = new ArrayList();

while (result.next()) {

AnnotationPersonRecord person = new AnnotationPersonRecord(); person.setFirstName(result.getString(2)); person.setMiddleName(result.getString(3)); person.setLastName(result.getString(4)); person.setDob(result.getString(5)); person.setComments(result.getString(6)); person.setFilename(result.getString(7)); person.setAnnotationStart(result.getString(8)); person.setAnnotationEnd(result.getString(9)); list.add(person);

}

if (list != null) {

for (int i=0; i < list.size(); i++) { AnnotationPersonRecord element =

(AnnotationPersonRecord)list.get(i);

}

AnnotationPrint.printArrayS( list );

}

}catch (Exception e) { logger.info(“Exception: “ + e.toString());

}

}

}

The createDocument(ResultSet rs) method works in conjunction with the XMLAction class to export annotation data to an XML file upon user request. Libraries are used from the dom4j package to craft an XML file artifact with the annotation text. The addElement method adds a new Element node to the topic branches of the document data structure:

static public org.dom4j.Document createDocument(ResultSet rs) {

org.dom4j.Document document = org.dom4j.DocumentHelper.createDocument(); org.dom4j.Element root = document.addElement( “Annotation” )

.addAttribute(“text”, “Default annotation”)

.addAttribute(“value”, “default”);

try {

org.dom4j.Element topic = null; int item=0;

while (rs.next()) { ++item;

topic = root.addElement( “person” ).addAttribute( “value”, “item” ).addAttribute( “text”, String.valueOf(item));

206

Developing Effective User Interfaces with JFC

topic.addElement( “attribute” ).addAttribute( “value”, “First Name” ).addAttribute( “text”, rs.getString(2) );

topic.addElement( “attribute” ).addAttribute( “value”, “Middle Name” ).addAttribute( “text”, rs.getString(3) );

topic.addElement( “attribute” ).addAttribute( “value”, “Last Name” ).addAttribute( “text”, rs.getString(4) );

topic.addElement( “attribute” ).addAttribute( “value”, “DOB” ).addAttribute( “text”, rs.getString(5) );

topic.addElement( “attribute” ).addAttribute( “value”, “Comments”

).addAttribute( “text”, rs.getString(6) );

topic.addElement( “attribute” ).addAttribute( “value”, “Filename” ).addAttribute( “text”, rs.getString(7) );

}

}catch (Exception sqle) { logger.info(“SQLException: “ + sqle.toString());

}

return document;

}

The XMLAction class establishes a database connection to the annotationtest database and performs a select operation so that the attributes of the annotation table will be output to an XML file. The data collected from the SQL operation is passed to the createDocument method described earlier:

public class XmlAction extends AbstractAction { public XmlAction() {

super(“XML”, new ImageIcon(“icons/xml.gif”));

}

public void actionPerformed(ActionEvent ev) { logger.info(“Generating XML.”);

try { Class.forName(“org.gjt.mm.mysql.Driver”); Connection conn =

DriverManager.getConnection(“jdbc:mysql://localhost/annotationtest”,

“”, “”);

PreparedStatement preparedStmt =

conn.prepareStatement(“SELECT * FROM PERSON WHERE FILENAME = ?”); preparedStmt.setString( 1, filename.toString());

ResultSet result = preparedStmt.executeQuery();

XMLWriter writer = new XMLWriter(new FileWriter( “Annotation.xml” ), OutputFormat.createPrettyPrint());

writer.write( createDocument( result ) ); writer.close();

}catch(Exception e) { logger.info(“Exception: “ + e.toString());

}

}

}

The ExcelAction class implements the Open-source Jakarta POI libraries to convert the Person table data to an Excel spreadsheet document. New workbook and sheet objects are created with the POI libraries and the annotation attributes that make up the annotation table are saved to those objects. For demonstration purposes, only the first, middle, and last name values are placed in the worksheet template:

207

Chapter 4

public class ExcelAction extends AbstractAction { public ExcelAction() {

super(“Excel”, new ImageIcon(“icons/excel.gif”));

}

public void actionPerformed(ActionEvent ev) { logger.info(“Generating Excel Spreadsheet.”); int rownum;

try {

FileOutputStream out = new FileOutputStream(“annotations.xls”);

HSSFWorkbook wb = new HSSFWorkbook();

HSSFSheet s = wb.createSheet();

HSSFRow r = null;

HSSFCell c = null;

HSSFCellStyle cs = wb.createCellStyle();

HSSFDataFormat df = wb.createDataFormat();

HSSFFont f = wb.createFont();

f.setFontHeightInPoints((short) 12);

cs.setFont(f);

cs.setDataFormat(HSSFDataFormat.getBuiltinFormat(“text”));

wb.setSheetName(0, “Test”, HSSFWorkbook.ENCODING_COMPRESSED_UNICODE ); // set title row

String[] titles = {“First Name”, “Middle Name”, “Last Name” }; r = s.createRow(0);

for (int i=0; i < titles.length; i++ ) {

s.setColumnWidth((short) (i + 1), (short) ((50 * 8) / ((double) 1 /

20)));

c = r.createCell((short) (i + 1)); c.setCellStyle(cs);

c.setEncoding( HSSFCell.ENCODING_COMPRESSED_UNICODE ); c.setCellValue( titles[i] );

}

The following code segment demonstrates how the SQL construct is built and executed so that the data collected can be saved to the Excel template file:

try { Class.forName(“org.gjt.mm.mysql.Driver”); Connection conn =

DriverManager.getConnection(“jdbc:mysql://localhost/annotationtest”,

“”, “”);

PreparedStatement preparedStmt = conn.prepareStatement(“SELECT * FROM PERSON”);

ResultSet result = preparedStmt.executeQuery(); int row = 1;

while (result.next()) {

208

Developing Effective User Interfaces with JFC

r = s.createRow(row);

c = r.createCell((short) (1)); c.setCellStyle(cs);

c.setEncoding( HSSFCell.ENCODING_COMPRESSED_UNICODE ); c.setCellValue( result.getString(2) );

c = r.createCell((short) (2)); c.setCellStyle(cs);

c.setEncoding( HSSFCell.ENCODING_COMPRESSED_UNICODE ); c.setCellValue( result.getString(3) );

c = r.createCell((short) (3)); c.setCellStyle(cs);

c.setEncoding( HSSFCell.ENCODING_COMPRESSED_UNICODE );

c.setCellValue( result.getString(4) ); row++;

}

}catch (Exception e) { logger.info(“Exception: “ + e.toString());

}

wb.write(out);

out.close();

} catch(IOException ioe) { logger.info(“IOException= “ + ioe.toString()); }

}

}

The OpenAction class uses the JFileChooser class to enable users to dynamically determine the files that will read into the AnnotationEditor for annotation operations. When a user selects the Open link in the menu bar, the showOpenDialog method will pop up a dialog box that allows users to drill across the system’s file structures for retrieval and manipulation:

// An action that opens an existing file class OpenAction extends AbstractAction {

public OpenAction() {

super(“Open”, new ImageIcon(“icons/open.gif”));

}

//Query user for a filename and attempt to open and read the file into the

//text component.

public void actionPerformed(ActionEvent ev) { JFileChooser chooser = new JFileChooser();

if (chooser.showOpenDialog(AnnotationEditor.this) != JFileChooser.APPROVE_OPTION)

return;

filename = chooser.getSelectedFile(); if (filename == null)

return;

FileReader reader = null; try {

reader = new FileReader(filename); textComp.read(reader, null);

// read annotations and markup text here try {

Class.forName(“org.gjt.mm.mysql.Driver”);

209

Chapter 4

The code snippet below establishes a database connection with the annotationtest database to retrieve the annotations associated with the document opened in the code above. Once all of the annotations have been retrieved, then the text associated with those annotations is highlighted in the AnnotationEditor application:

Connection conn = DriverManager.getConnection(“jdbc:mysql://localhost/annotationtest”,

“”, “”);

PreparedStatement preparedStmt =

conn.prepareStatement(“SELECT ANNOTATION_START, ANNOTATION_END, ANNOTATION_TEXT FROM ANNOTATION_TABLE”);

ResultSet result = preparedStmt.executeQuery(); while (result.next()) {

highlight(textComp, result.getString(3));

}

}catch (Exception e) { logger.info(“Exception: “ + e.toString());

}

}catch (IOException ex) { JOptionPane.showMessageDialog(AnnotationEditor.this, “File Not Found”, “ERROR”, JOptionPane.ERROR_MESSAGE);

}finally {

if (reader != null) { try {

reader.close();

} catch (IOException x) {}

}

}

}

}

// main method omitted for the sake of brevity

}

The importance of dialog components cannot be understated because they allow applications to organize and prioritize data for your user interface so that information can be properly propagated to your data persistence mechanism, which might be a database or collection class implementation. When an application invokes a dialog box, it forces the user to aggregate information in a controlled fashion from a user so that information can be added or modified for your application’s operations.

Some dialog applications are modal, which means that they block all user input to windows in a program when they are visible, but the AnnotationDialog application is nonmodal because it uses the JDialog class directly.

The AnnotationDialog application below enables users to dynamically add information about people that a user has marked for insertion by the user in the editor application (see Figure 4-17).

Person

Export Excel

Figure 4-17

210

Developing Effective User Interfaces with JFC

//[AnnotationPeopleDialog.java]

//package name and import statements omitted

public class AnnotationPeopleDialog extends JDialog implements ActionListener {

// declarations omitted for the sake of brevity [please look at source downloads] public interface Command {

public void execute();

}

public AnnotationPeopleDialog(String annotation, String filename,

int annotationStart, int annotationEnd) { // parameter save omitted for the sake of brevity createGUIDisplay();

}

public AnnotationPeopleDialog() { createGUIDisplay();

}

public void createGUIDisplay() {

JPanel panelAll = new JPanel(new GridLayout(0,1,5,5)); JPanel panelTest1 = new JPanel(new GridLayout(0,1,5,5)); panelTest1.add(panelGUI());

JPanel panelTest2 = new JPanel(new GridLayout(0,1,5,5)); panelTest2.add(panelComments());

panelAll.add(panelTest1);

panelAll.add(panelTest2);

String[] name = annotation.trim().split(“[ ]+”); if (name.length == 3) {

firstName.setText(name[0]);

middleName.setText(name[1]);

lastName.setText(name[2]); } else {

firstName.setText(name[0]);

lastName.setText(name[1]);

}

getContentPane().add(panelAll); getContentPane().setVisible(true);

pack();

}

The panelGUI() method establishes a GridLayout display so that users can enter user data that will be affiliated with highlighted text inside the AnnotationEditor. Figure 4-16 represents the GUI presentation that will be rendered when the panelGUI() method is invoked:

public JPanel panelGUI() {

JPanel peoplePanel = new JPanel(new GridLayout(0,2,5,5));

firstName = new JTextField(20); middleName = new JTextField(20); lastName = new JTextField(20);

211

Chapter 4

model1 = new SpinnerDateModel(); model1.setCalendarField(Calendar.WEEK_OF_MONTH); spinner1 = new JSpinner(model1);

JSpinner.DateEditor editor1 = new JSpinner.DateEditor(spinner1, “MM/dd/yyyy”); spinner1.setEditor(editor1);

// add items to panel

peoplePanel.add(new JLabel(“First Name:”)); peoplePanel.add(firstName); peoplePanel.add(new JLabel(“Middle Name:”)); peoplePanel.add(middleName);

peoplePanel.add(new JLabel(“Last Name:”)); peoplePanel.add(lastName); peoplePanel.add(new JLabel(“Date of Birth:”)); peoplePanel.add(spinner1);

titledBorder = BorderFactory.createTitledBorder(new EtchedBorder (EtchedBorder.LOWERED), “Person Information”);

titledBorder.setTitleJustification(TitledBorder.LEFT);

peoplePanel.setBorder(titledBorder);

return peoplePanel;

}

The panelComments() method generates the text area component that collects user comments that will be associated with the name and date of birth text in the AnnotationPeopleDialog class:

public JPanel panelComments() {

JPanel peoplePanel = new JPanel(new GridLayout(0,1,5,5));

peopleComments = new JTextArea(“”); peopleComments.setFont(new Font(“Serif”, Font.ITALIC, 16)); peopleComments.setLineWrap(true); peopleComments.setWrapStyleWord(true);

areaScrollPane1 = new JScrollPane(peopleComments); areaScrollPane1.setVerticalScrollBarPolicy(

JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); areaScrollPane1.setPreferredSize(new Dimension(50, 50)); areaScrollPane1.setBorder(BorderFactory.createCompoundBorder(

BorderFactory.createCompoundBorder(

BorderFactory.createTitledBorder(“ People Comments”), BorderFactory.createEmptyBorder(5,5,5,5)), areaScrollPane1.getBorder()));

addPersonRecord = new JAddPersonButton(“ Add Person Record “); addPersonRecord.addActionListener(this); addPersonRecord.setFont(navigationFont); addPersonRecord.setBorder(raisedBevelBorder);

peoplePanel.add(areaScrollPane1);

peoplePanel.add(addPersonRecord);

return peoplePanel;

}

212

Developing Effective User Interfaces with JFC

The ComboListener class listens for user actions on the combobox component on the GUI display. The actionPerformed(ActionEvent e) method implements the Command pattern so that user activities are handled appropriately by the AnnotationEditor application:

class ComboListener implements ActionListener { public void actionPerformed(ActionEvent e) { JComboBox cb = (JComboBox)e.getSource();

logger.info(“Combo selection= “ + (String)cb.getSelectedItem());

}

}

public void actionPerformed(ActionEvent e) { Command obj = (Command)e.getSource(); try {

obj.execute();

}catch (Exception ex) { logger.info(“Exception: “ + ex);

}

}

The JAddPersonButton method polymorphically invokes the execute() method, which uses the JOptionPane class to pop up a standard dialog box to collect relevant annotation data that relates to the person highlighted in the Annotation Editor. The showConfirmDialog method asks the user whether or not the information entered should be persisted by the application or neglected when the dialog box exits. If the user selects Yes when queried, “Are You Sure?”, then an SQL prepared statement is constructed to aggregate the user information for insertion to the person and annotation_table tables, respectively:

class JAddPersonButton extends JButton implements Command {

public JAddPersonButton(String caption) { super(caption); } public void execute() {

int selection = JOptionPane.showConfirmDialog(null, “Are you sure?”, “People database insert.”,

JOptionPane.YES_NO_CANCEL_OPTION); if (selection == 0) {

try { Class.forName(“org.gjt.mm.mysql.Driver”); Connection conn =

DriverManager.getConnection(“jdbc:mysql://localhost/annotationtest”, “”, “”); PreparedStatement preparedStmt =

conn.prepareStatement(“INSERT INTO PERSON (FIRST_NAME, MIDDLE_NAME, LAST_NAME, DOB, COMMENTS, FILENAME, ANNOTATION_START, ANNOTATION_END) VALUES (?,?,?,?,?,?,?,?)”);

preparedStmt.setString( 1, firstName.getText().toString() ); preparedStmt.setString( 2, middleName.getText().toString() ); preparedStmt.setString( 3, lastName.getText().toString() ); preparedStmt.setString( 4,

((JSpinner.DateEditor)spinner1.getEditor()).getTextField().getText() ); preparedStmt.setString( 5, peopleComments.getText().toString() ); preparedStmt.setString( 6, filename );

213

Chapter 4

preparedStmt.setInt( 7, annotationStart ); preparedStmt.setInt( 8, annotationEnd ); preparedStmt.executeUpdate();

preparedStmt =

conn.prepareStatement(“INSERT INTO ANNOTATION_TABLE (F_FILENAME, ANNOTATION_TYPE, ANNOTATION_START, ANNOTATION_END, ANNOTATION_TEXT) VALUES (?,?,?,?,?)”);

preparedStmt.setString( 1, filename ); preparedStmt.setString( 2, “PERSON” ); preparedStmt.setInt( 3, annotationStart); preparedStmt.setInt( 4, annotationEnd); preparedStmt.setString( 5, annotation ); preparedStmt.executeUpdate();

conn.close();

}catch(Exception e) { logger.info(“Exception = “ + e.toString());}

}else {

logger.info(“User selected: NO”);

}

hidePanel();

}

}

public void hidePanel() { setVisible(false);

}

// main method omitted for brevity

}

Managing Navigation Flows in Swing

Applications

Installation wizards are common Swing applications to consign software applications and their libraries to their file systems during their development or deployment tasks. Wizards typically perform initialization activities, gather user directory designations, and perform post-installation tasks for clean-up actions by leading users through a series of requests to ensure that applications and their libraries are configured properly for operations. This last segment of the chapter will demonstrate how an InstallationWizard application can be developed using the State Pattern, a GoF behavioral pattern, to delegate behaviors across objects during user navigations at run time. Each state, or step, of the wizard is encapsulated as an object, which is affiliated to a subclass of an abstract class for proper state management This same application could have easily been developed with the CardLayout manager using its first(), last(), previous(), and next() methods, but the intent was to show how you could manage those flows in a different fashion. Additionally, the Singleton pattern is implemented in the sample application to demonstrate how a single object can be created and referenced from a program without incurring the overhead of creating superfluous objects.

214

Developing Effective User Interfaces with JFC

The following table outlines some of benefits and drawbacks of implementing both patterns in your applications.

Pattern

Benefits

Consequences

Singleton

Direct control over how many instances

 

can be created

 

Ensures that a class has only one instance

 

and enforces controlled access to the

 

sole instance

Inability to subclass an application that implements it, which prevents extendibility

State

Allows an object to modify its behavior

Preponderance of classes to

 

when its state changes internally

support the different states of an

 

 

application

 

Localizes all behavior of a particular

 

 

state in a single object

 

 

Polymorphically defines behaviors and

 

 

states of an object

 

The individual panel display components represent state-specific behaviors that are derived from the abstract State class. The application maintains a pointer to the current state position in the installation process and reacts to changes by the user as navigation is performed in a forward and backward direction using the Previous and Next buttons on the GUI display (see Figure 4-18).

Figure 4-18

The InstallationWizard application implements two JPanel components, componentPanel and buttonPanel, to display the individual Swing visualizations for user input and the buttons used for previous/next operations, respectively:

//[InstallationWizard.java]

//package name and import statements omitted

public class InstallationWizard extends JFrame implements ActionListener {

private static Logger logger = Logger.getLogger(“InstallationWizard”);

215

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]