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

Professional Java.JDK.5.Edition (Wrox)

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

Chapter 4

The TestStrategy interface is implemented by the StartsWithAEIOU and AlphabeticChars classes so that the CardLayoutPanel application can apply different string algorithms to the user-specified text. Regular expression constructs are used to determine the patterns of the strings passed into the test method:

public interface TestStrategy { public boolean test(String s);

}

public class StartsWithAEIOU implements TestStrategy { public boolean test(String s) {

if( s == null || s.length() == 0) return false; return (s.toUpperCase().charAt(0) == ‘A’ || s.toUpperCase().charAt(0) == ‘E’ || s.toUpperCase().charAt(0) == ‘I’ || s.toUpperCase().charAt(0) == ‘O’ ||

s.toUpperCase().charAt(0) == ‘U’ );

}

}

public class convertUppercase implements TestStrategy { public boolean test(String s) {

if( s == null || s.length() == 0 ) return false; Pattern pattern = Pattern.compile(“[a-zA-Z]”); Matcher match = pattern.matcher(s);

if (!match.find()) { return false;

} else {

return (true);

}

}

}

// main routine omitted for brevity

}

Figure 4-14 represents the CardLayoutPanel application modeled in the source code above. Users can enter text in the card layout show in the top panel and hit either strategy pattern button to apply the appropriate Strategy algorithm to that text. Results of those actions will be rendered in the card layout below. All of the button components employ the Command pattern to allow the application to determine at run time the proper execute() method to invoke based on the user’s navigations.

196

Developing Effective User Interfaces with JFC

Figure 4-14

JFrame and JDialog Components

The JFrame class is used in Java applications to construct a top-level window for GUI components with a border and title, as well as buttons for minimization, maximization, and closure. The JDialog class is used to build pop-up windows for user decision making and aggregating unified data entries. Both classes are important features of the Swing libraries to build cohesive GUI components.

This portion of the chapter will disclose how the JFrame and JDialog classes can be used in tandem to build an effective Annotation Editor application. The sample application will allow users to mark up text files so that meta data, in the form of comments and associated attributes, can be linked to a document passage from a user-specified file. Annotations typically mean comments, notes, or explanations that can be attached to the text without actually needing to touch the document. When a user opens a document in the editor, all meta data text that is persisted in a MySQL database will be attached to the text marked up by users who have commented on passages in that file (see Figure 4-15).

197

Chapter 4

Figure 4-15

The code here demonstrates how the Annotation Editor was developed. A MySQL database is used to persist meta data associated with marked text in the document. Additionally, logic was added to save the annotation to Microsoft Excel spreadsheet artifacts using Jakarta POI libraries, as well as XML documents using dom4j libraries:

// package name and import statements omitted

public class AnnotationEditor extends JFrame {

// declaration omitted for sake of brevity [please check out source download]

public AnnotationEditor() { super(“Annotation Editor”);

initPopupMenu();

popupListener = new PopupListener(); componentListener = new ComponentListener();

textComp = createTextComponent(); textComp.addMouseListener(popupListener); textComp.addCaretListener(componentListener); textComp.setBorder(BorderFactory.createCompoundBorder(

BorderFactory.createCompoundBorder(

BorderFactory.createTitledBorder(“Text”),

BorderFactory.createEmptyBorder(5,5,5,5)),

textComp.getBorder()));

textComp.setEditable(false);

scrollPane = new JScrollPane(); scrollPane.setVerticalScrollBarPolicy(JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setPreferredSize(new Dimension(350, 150));

198

Developing Effective User Interfaces with JFC

scrollPane.setBorder(BorderFactory.createCompoundBorder(

BorderFactory.createCompoundBorder(

BorderFactory.createTitledBorder(“Annotations”),

BorderFactory.createEmptyBorder(5,5,5,5)),

scrollPane.getBorder()));

root = new DefaultMutableTreeNode(“Annotations”); tree = new JTree(root); scrollPane.getViewport().add( tree );

content = getContentPane(); content.add(textComp, BorderLayout.CENTER); content.add(createToolBar(), BorderLayout.NORTH); content.add(scrollPane, BorderLayout.SOUTH); setJMenuBar(createMenuBar());

setSize(700, 500);

}

The AnnotationEditor(String filename) constructor method invokes the createTextComponent() method to instantiate a JTextArea component used to display the file used for annotating text. The FileReader class is used to read the file for annotation and posit in the text area display textComp. The center and north quadrants of a BorderLayout manager are used to display the annotation file and toolbar components:

public AnnotationEditor(String filename) { super(“Annotation Editor”);

textComp = createTextComponent(); File file = new File(filename); if (file == null) return;

FileReader reader = null; try {

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

}catch (IOException ex) { JOptionPane.showMessageDialog(AnnotationEditor.this,

“File Not Found”, “ERROR”, JOptionPane.ERROR_MESSAGE);

}

finally {

if (reader != null) { try {

reader.close();

} catch (IOException x) {}

}

}

Container content = getContentPane(); content.add(textComp, BorderLayout.CENTER); content.add(createToolBar(), BorderLayout.NORTH); setJMenuBar(createMenuBar());

setSize(320, 240);

}

protected JTextComponent createTextComponent() {

199

Chapter 4

JTextArea ta = new JTextArea(); ta.setLineWrap(true);

return ta;

}

The initPopupMenu() method kicks off a dialog panel that allows users to input meta data associated with the person highlighted in the editor display. The actionPeformed(ActionEvent evt) method is implemented to handle mouse events when the user right-clicks text within the GUI display. If the user selects the Person link inside the pop-up panel, then the application will pop up the AnnotationPeopleDialog component so that users can attach meta data to the text highlighted by the user:

protected void initPopupMenu() { popup = new JPopupMenu();

ActionListener menuListener = new ActionListener() { public void actionPerformed(ActionEvent event) {

if (“Person”.equals(event.getActionCommand())) {

String[] markedText = textComp.getSelectedText().trim().split(“[

]+”);

for (int i=0; i < markedText.length; i++) AnnotationPeopleDialog dlg =

new AnnotationPeopleDialog(textComp.getSelectedText().trim(), filename.toString(), getAnnotationStart(), getAnnotationEnd());

dlg.show();

highlight(textComp, textComp.getSelectedText().trim()); } else if (“Annotations”.equals(event.getActionCommand())) {

AnnotationSearchResultsDialog d = new AnnotationSearchResultsDialog(); d.show();

}

}

};

Users can kick off the dialog panel for annotation entry by right-clicking their mouse inside the GUI presentation, which will pop up a panel with two user selections, Person or Export Excel. If the user selects Person, then the dialog will present the data input form. Alternatively, if the user clicks Export Excel, then all of the annotations that reside in the database will be exported to an Excel spreadsheet. Figure 4-16 illustrates how the AnnotationPeopleDialog display is rendered so that users can attach meta data to the highlighted Gillian Stern text.

200

Developing Effective User Interfaces with JFC

Figure 4-16

// add images and listeners

itemPerson = new JMenuItem(“Person”, createImageIcon(“images/people.gif”)); itemPerson.setActionCommand(“Person”); itemPerson.addActionListener(menuListener);

popup.add(itemPerson);

itemExportExcel = new JMenuItem(“Export Excel”, createImageIcon(“images/excel.gif”));

itemExportExcel.setActionCommand(“Export Excel”); itemExportExcel.addActionListener(menuListener); popup.add(itemExportExcel);

//The code here is commented out, but is a new feature of J2SDK1.5 that

//allows users to easily implement context-sensitive menus that appear when

//a user right-clicks over a specified area in a GUI display. Rather than

//checking the trigger within the MouseEvent class, control is passed to

//to the JpopupMenu class itself. If the code below is commented out, then

//the PopupListener class below should be omitted, as well as the

//instantiation of that class above and its ties to the JTextArea mouse

//listener in the textComp.addMouseListener(popupListener) operation

//

//JButton button = new JButton(“Test”);

//button.setComponentPopupMenu(popup);

//getContentPane().add(button, BorderLayout.CENTER);

}

class PopupListener extends MouseAdapter {

public void mousePressed(MouseEvent e) { showPopup(e); } public void mouseClicked(MouseEvent e) { showPopup(e); } public void mouseReleased(MouseEvent e) { showPopup(e); }

201

Chapter 4

private void showPopup(MouseEvent e) { if (e.isPopupTrigger()) {

popup.show(e.getComponent(), e.getX(), e.getY());

}

}

}

The ComponentListener class implements the CaretListener interface to process the user marking activities inside the editor application. The Select operation in the PreparedStatement below takes the start and end positions of the annotation text to determine what annotations have been affiliated with that text:

public class ComponentListener implements CaretListener {

public void caretUpdate(CaretEvent e) { displaySelectionInfo(e.getDot(), e.getMark());

}

protected void displaySelectionInfo(final int dot, final int mark) { SwingUtilities.invokeLater(new Runnable() {

public void run() {

setAnnotationInfo(mark, dot); // retrieve annotation text try {

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

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

conn.prepareStatement(“SELECT F_FILENAME, ANNOTATION_TYPE, ANNOTATION_TEXT FROM ANNOTATION_TABLE WHERE ? >= ANNOTATION_START AND ? <= ANNOTATION_END”);

preparedStmt.setInt( 1, mark ); preparedStmt.setInt( 2, dot );

ResultSet result = preparedStmt.executeQuery(); if (result != null) {

String annotationFilename=””; String annotationType=””; while (result.next()) {

annotationFilename = result.getString(1); annotationType = result.getString(2);

}

If the annotation filename is not empty, then all of the attributes of the annotation file are retrieved (so that they can be added to the JTree component for visualization) and the database connection is closed:

if (!annotationFilename.equals(“”)) { preparedStmt =

conn.prepareStatement(“SELECT * FROM “ + annotationType +

“ WHERE FILENAME = ?” +

“ AND ? >= ANNOTATION_START AND ? <= ANNOTATION_END”); preparedStmt.setString( 1, annotationFilename ); preparedStmt.setInt( 2, mark );

preparedStmt.setInt( 3, dot );

202

Developing Effective User Interfaces with JFC

result = preparedStmt.executeQuery();

int itemsCount = 0;

root = new DefaultMutableTreeNode(“Annotations”); tree = new JTree(root);

DefaultMutableTreeNode items;

if (annotationType.equals(“PERSON”)) { while (result.next()) {

items = new DefaultMutableTreeNode(“Item” +

(++itemsCount));

root.add(items);

items.add(new DefaultMutableTreeNode(“First Name= “ +

result.getString(2)));

items.add(new DefaultMutableTreeNode(“Middle Name= “ +

result.getString(3)));

items.add(new DefaultMutableTreeNode(“Last Name= “ +

result.getString(4)));

items.add(new DefaultMutableTreeNode(“DOB= “ +

result.getString(5)));

items.add(new DefaultMutableTreeNode(“Comments= “ +

result.getString(6)));

}

}

scrollPane.getViewport().add( tree ); tree.expandRow(0);

}

}

conn.close();

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

}

}

});

}

}

// setAnnotationInfo(), getAnnotationStart() and getAnnotationEnd() omitted for the sake of brevity

The createToolBar() method instantiates a new toolbar component to add the actions that a user can perform in the editor application. Those actions include the opening and printing of files and the exporting of annotations to XML and Excel spreadsheet artifacts:

protected JToolBar createToolBar() { JToolBar bar = new JToolBar(); bar.add(getOpenAction()).setText(“”); bar.add(getPrintAction()).setText(“”);

bar.add(getXmlAction()).setText(“”); bar.add(getExcelAction()).setText(“”); return bar;

}

203

Chapter 4

The highlight and removeHighlights methods are invoked by the user when text inside the editor is marked and unmarked by mouse activities by the user. The text marked inside the text area component textComp is collected by the invocation of the getHighlighter() method, and the text is highlighted in the view by the addHighlight method. Alternatively, text highlights are removed by invoking the removeHighlights method:

public void highlight(JTextComponent textComp, String pattern) {

try {

hilite = textComp.getHighlighter(); doc = textComp.getDocument();

String text = doc.getText(0, doc.getLength()); int pos = 0;

// save annotation position and length for future reference int x = text.indexOf(pattern, pos);

if (x > 0) {

hilite.addHighlight(x, x+pattern.length(), myHighlightPainter);

}

}catch (BadLocationException e) { logger.severe(“BadLocationException e” + e.toString());

}

}

public void removeHighlights(JTextComponent textComp) { Highlighter hilite = textComp.getHighlighter(); Highlighter.Highlight[] hilites = hilite.getHighlights();

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

if (hilites[i].getPainter() instanceof MyHighlightPainter) { hilite.removeHighlight(hilites[i]);

}

}

}

The HighlightPainter class is instantiated with color attributes sent to the Color constructor so that all highlights in the text document persist the same color throughout the text. The createMenuBar() method returns a JMenuBar object with actions for opening and printing files, as well as for persisting the annotations in XML and Microsoft Excel files and finally for exiting the application altogether:

Highlighter.HighlightPainter myHighlightPainter = new MyHighlightPainter(new Color(255,204,51));

class MyHighlightPainter extends DefaultHighlighter.DefaultHighlightPainter { public MyHighlightPainter(Color color) {

super(color);

}

}

protected JMenuBar createMenuBar() { JMenuBar menubar = new JMenuBar(); JMenu file = new JMenu(“File”); menubar.add(file);

file.add(getOpenAction());

204

Developing Effective User Interfaces with JFC

file.add(getPrintAction());

file.add(getXmlAction());

file.add(getExcelAction());

file.add(new ExitAction()); return menubar;

}

The Action interface provides an extension to the ActionListener interface whereby an application needs to implement an actionPerformed() method to obtain desirable system behavior. That behavior could be for a fly-over text display or to modify component event generation. The AnnotationEditor establishes four user actions for File Open, Print, XML, and Excel spreadsheet generation operations.

The peopleAction method kicks off a dialog that allows users to add people information that has been marked in the editor display. When invoked, the application creates a new instance of the AnnotationPeopleDialog class, the class reference invoked the show() method to display the panel to the user for data input:

protected Action getOpenAction() { return openAction; } protected Action getPrintAction() { return printAction; } protected Action getXmlAction() { return xmlAction; } protected Action getExcelAction() { return excelAction; }

protected JTextComponent getTextComponent() { return textComp; }

protected Action getPeopleAction() { return peopleAction; }

public class peopleAction extends AbstractAction { public peopleAction() {

super(“People”, new ImageIcon(“images/people.gif”));

}

public void actionPerformed(ActionEvent ev) { AnnotationPeopleDialog dlg = new AnnotationPeopleDialog(); dlg.show();

}

}

public class ExitAction extends AbstractAction { public ExitAction() { super(“Exit”); }

public void actionPerformed(ActionEvent ev) { System.exit(0); }

}

The PrintAction class collects all information from the Person database table and kicks off a print GUI to allow users to dictate where the aggregated people information will be printed. All of the annotation text that will be submitted for printout will be aggregated through the Select construct placed in the PreparedStatement that follows. Each individual row of the Person table will be stuffed into an instance of a AnnotationPersonRecord object and added to a list collection before it is passed to the printArrays method of the AnnotationPrint class:

public class PrintAction extends AbstractAction { public PrintAction() {

super(“Print”, new ImageIcon(“icons/print.gif”));

}

public void actionPerformed(ActionEvent ev) {

205

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