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

Professional Java.JDK.5.Edition (Wrox)

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

Chapter 4

[QuarterHandler.java]

// package name and import statements omitted public class QuarterHandler extends TestHandler {

private static Logger logger = Logger.getLogger(“QuarterHandler”); private int count;

public void handleRequest(int coinAmount) {

int numberQuarters = coinAmount / 25;

coinAmount %= 25; this.count = numberQuarters;

if (coinAmount > 0) getSuccessor().handleRequest(coinAmount);

}

public int getCount() { return this.count;

}

}

Figure 4-6 represents the finished product of the FlowLayoutPanel application. When users add a dollar amount in the text field of the GUI application and click the Determine Coins button, the coin distribution will be displayed in the panel below the Currency panel. With the Chain of Responsibility pattern implementation, the coins are handled sequentially from quarters to dimes to nickels to pennies until all coins have been accounted for. An important point to take away from the Chain of Responsibility pattern is that rather than calling a single method to satisfy a request, multiple methods in a chain have a chance to fulfill that request.

Figure 4-6

166

Developing Effective User Interfaces with JFC

GridLayout

The GridLayout manager arranges its components in a rectangular, gridlike fashion. When components are added to the GridLayout manager, rows are populated first.

The constructor methods for the GridLayout manager are shown in the method summary table that follows.

Method

Description

public GridLayout()

No parameters — creates a grid layout

 

with a default of one column per com-

 

ponent, in a single row

public GridLayout(int rows, int columns)

Row and column parameters specify the size of the grid

Public GridLayout(int rows,

int columns, int hGap, int vGap)

Row and column parameters specify the size of the grid and the hGap and vGap parameters specify the horizontal and vertical pixels between components

The following GridLayout example processes mouse events on buttons generated with Java 2D classes. Figure 4-7 shows how the buttons are organized on the GridLayoutPanel display.

GridLayout

 

buttonPanel

dataPanel

Rectangle2D

 

 

dbPanel

 

JTree

 

mouseButtonPanel

 

MouseListener

MouseListener

 

Figure 4-7

167

Chapter 4

The following GridLayoutPanel code segment aggregates the different Java 2D components along with the Swing JTree and JTable components on the grid display. The Java2DPanel and Java2DPanelMouseover classes generate Java 2D button images that set the Cola row value of the JTable component, and store the proper Cola data value to the JTree component when the user clicks on them:

[GridLayoutPanel.java]

// package name and import statements omitted

public class GridLayoutPanel extends JPanel {

// declarations omitted for the sake of brevity [Please check download code] public GridLayoutPanel() {

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

DBPanel dbPanel = new DBPanel();

Java2DPanel buttonPanel = new Java2DPanel(dbPanel);

Java2DPanelMouseover mouseButtonPanel = new Java2DPanelMouseover(dbPanel); JPanel dataPanel = new JPanel(new GridLayout(0,1,5,5)); dbPanel.add(mouseButtonPanel);

panelAll.add(dbPanel);

panelAll.add(buttonPanel);

panelAll.add(dataPanel);

add(panelAll);

setVisible(true);

}

// main method omitted for the sake of brevity

}

The Java2DPanel class implements the Rectangle2D class to create buttons to obtain information concerning six different Cola selections. These buttons are attached to a mouseListener handler to determine if a user has clicked the mouse inside one of those buttons. The setPreferredSize method allows the constructor class for Java2DPanel to set the panel display to a desired dimension using height and width values:

[Java2Dpanel.java]

// package name and import statements omitted

public class Java2DPanel extends JPanel implements MouseListener {

Rectangle2D rect1, rect2, rect3, rect4, rect5, rect6;

DBPanel dbRef;

public Java2DPanel(DBPanel db) {

dbRef = db;

168

Developing Effective User Interfaces with JFC

rect1 = new Rectangle2D.Double(25, 25, 100, 100); rect2 = new Rectangle2D.Double(150, 25, 100, 100); rect3 = new Rectangle2D.Double(25, 150, 100, 100); rect4 = new Rectangle2D.Double(150, 150, 100, 100); rect5 = new Rectangle2D.Double(25, 275, 100, 100); rect6 = new Rectangle2D.Double(150, 275, 100, 100);

this.addMouseListener(this);

setBackground(Color.white); setPreferredSize(new Dimension(300, 200));

}

The paintComponent(Graphics g) method is called when a window becomes visible or is resized, and when a mouse listener detects a new user-generated event to draw the background graphics components on the panel display. Six rectangle class components are constructed by instantiating Rectangle class objects and filling them by implementing the Graphics2D fill(Shape s) method:

public void paintComponent(Graphics g) { clear(g);

Graphics2D g2 = (Graphics2D) g; g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING,

RenderingHints.VALUE_ANTIALIAS_ON);

Rectangle rectangle1 = new Rectangle(35, 40, 100, 100);

Rectangle rectangle2 = new Rectangle(160, 40, 100, 100);

Rectangle rectangle3 = new Rectangle(35, 165, 100, 100);

Rectangle rectangle4 = new Rectangle(160, 165, 100, 100);

Rectangle rectangle5 = new Rectangle(35, 290, 100, 100);

Rectangle rectangle6 = new Rectangle(160, 290, 100, 100);

g2.setPaint(new Color(204, 255, 153)); g2.fill(rectangle1); g2.fill(rectangle2); g2.fill(rectangle3); g2.fill(rectangle4); g2.fill(rectangle5); g2.fill(rectangle6);

g2.setColor(new Color(123,123,45)); g2.fill(rect1);

g2.fill(rect2);

Now that the six different background buttons have been created and filled, the foreground buttons are created by using the Graphics2D drawstring(String str, int x, int y) method to place string text on the button display and the fill(Shape s) method to draw the button shape:

g2.setColor(Color.black);

g2.setFont(new Font(“Serif”, Font.BOLD, 18)); g2.drawString(“Cola 1”, (float)(rect1.getX())+25,

(float)(rect1.getY()+rect1.getHeight()/2)); g2.drawString(“Cola 2”, (float)(rect2.getX())+25,

(float)(rect2.getY()+rect2.getHeight()/2));

169

Chapter 4

g2.setColor(new Color(123,123,45)); g2.fill(rect3);

g2.fill(rect4);

g2.setColor(Color.black);

g2.setFont(new Font(“Serif”, Font.BOLD, 18)); g2.drawString(“Cola 3”, (float)(rect3.getX())+25,

(float)(rect3.getY()+rect3.getHeight()/2)); g2.drawString(“Cola 4”, (float)(rect4.getX())+25,

(float)(rect4.getY()+rect4.getHeight()/2));

g2.setColor(new Color(123,123,45)); g2.fill(rect5);

g2.fill(rect6);

g2.setColor(Color.black);

g2.setFont(new Font(“Serif”, Font.BOLD, 18)); g2.drawString(“Cola 5”, (float)(rect5.getX())+25,

(float)(rect5.getY()+rect5.getHeight()/2)); g2.drawString(“Cola 6”, (float)(rect6.getX())+25,

(float)(rect6.getY()+rect6.getHeight()/2));

}

The mousePressed(MouseEvent e) method checks the user’s mouse event to see if it was clicked inside one of the Rectangle2D button shapes. If the application detects a click inside the button display area, then the data values associated with that button will be set in the JTree and JTable components:

public void mousePressed(MouseEvent e) {

if ( insideRectangle(e.getX(), e.getY(), rect1.getX(), rect1.getY(), rect1.getWidth(), rect1.getHeight()) ) {

dbRef.setRow(0);

dbRef.addTreeData(0);

}

if ( insideRectangle(e.getX(), e.getY(), rect2.getX(), rect2.getY(), rect2.getWidth(), rect2.getHeight()) ) {

dbRef.setRow(1);

dbRef.addTreeData(1);

}

if ( insideRectangle(e.getX(), e.getY(), rect3.getX(), rect3.getY(), rect3.getWidth(), rect3.getHeight()) ) {

dbRef.setRow(2);

dbRef.addTreeData(2);

}

if ( insideRectangle(e.getX(), e.getY(), rect4.getX(), rect4.getY(), rect4.getWidth(), rect4.getHeight()) ) {

dbRef.setRow(3);

dbRef.addTreeData(3);

}

if ( insideRectangle(e.getX(), e.getY(), rect5.getX(), rect5.getY(), rect5.getWidth(), rect5.getHeight()) ) {

dbRef.setRow(4);

dbRef.addTreeData(4);

}

170

Developing Effective User Interfaces with JFC

if ( insideRectangle(e.getX(), e.getY(), rect6.getX(), rect6.getY(), rect6.getWidth(), rect6.getHeight()) ) {

dbRef.setRow(5);

dbRef.addTreeData(5);

}

}

The insideRectangle method returns a boolean true or false value depending on whether or not the user has clicked the mouse inside the button shape on the panel display based on the coordinates passed to the routine:

public boolean insideRectangle(int xMouse, int yMouse, double x, double y, double width, double height) {

if ( (xMouse >= x && xMouse <= x+width) && (yMouse >= y && yMouse <= y+height)

) {

return true;

}

return false;

}

protected void clear(Graphics g) { super.paintComponent(g);

}

public void mouseDragged(MouseEvent e) {} public void mouseReleased(MouseEvent e) {} public void mouseMoved (MouseEvent e) {} public void mouseEntered (MouseEvent e) {} public void mouseExited (MouseEvent e) {} public void mouseClicked (MouseEvent e) {}

// main method omitted for the sake of brevity

}

The Java2DPanelMouseover class only generates a single Java 2D button that acts differently than the Java2DPanel buttons in that when a user passes the mouse over the button, the Cola value will automatically be set in the JTree and JTable data stores. The Java2DPanel application requires that a user click inside the button display area to emulate the same behavior:

[Java2DPanelMouseover.java]

// package name and import statements omitted

public class Java2DPanelMouseover extends JPanel {

// declarations omitted for the sake of brevity [Please check download code] public Java2DPanelMouseover(DBPanel dbRef) {

this.dbRef = dbRef;

setPreferredSize(new Dimension(100, 100)); setSize(100,100);

171

Chapter 4

this.mouseOverColor = new Color(123,123,45); this.normalColor = new Color(204, 255, 153); this.paintColor = normalColor;

The addMouseListener method is used to track the individual mouse movements of the user across the panel component. When the user crosses enters the button space with the Cola 1 label, the mouseOverColor will displace the normalColor value and the JTable and JTree components will point to the data associated with the Cola1 item using the displayTableRow1() method:

this.addMouseListener(new MouseListener() { public void mouseEntered(MouseEvent e) {

displayTableRow1(); paintColor = mouseOverColor; repaint();

}

public void mouseExited(MouseEvent e) { paintColor = normalColor; repaint();

}

public void mouseDragged(MouseEvent e) {} public void mouseClicked(MouseEvent e) {} public void mousePressed(MouseEvent e) {} public void mouseReleased(MouseEvent e) {}

});

}

public void displayTableRow1() { dbRef.setRow(0); dbRef.addTreeData(0);

}

The paintComponent(Graphics g) method applies the proper paint color inside the Java 2D button using the value stored in the paintColor variable. The MouseEntered method sets the paintColor to the mouseOverColor value and when the user exits the button space, it is reset to the normalColor value:

public void paintComponent(Graphics g) {

Graphics2D g2d = (Graphics2D) g;

g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON);

Dimension d = this.getSize();

g2d.clearRect(0, 0, d.width, d.height);

int centerX = d.width / 2; int centerY = d.height / 2;

int xOffset = d.width / 2 - 3; int yOffset = d.height / 2 - 3;

g2d.setColor(this.paintColor);

172

Developing Effective User Interfaces with JFC

g2d.fillRect(0, 0, 100, 100);

g2d.setColor(Color.black);

g2d.setFont(new Font(“Serif”, Font.BOLD, 18));

g2d.drawString(“Cola 1”, 25, 50);

}

}

The DBPanel class below stores the six different Cola values in the JTable component and dynamically sets the row value inside the populated table associated with the button value as the user clicks on the different Java 2D button components. The DBPanel constructor method is called when the class is first invoked, where an object reference of the MyTableModel class, named mtm, invokes the

populateTable(String[] s) method to initialize the table values to empty strings prior to establishing the layout managers needed to place the visual components on. Three different GridLayout managers are instantiated, and two of those — panelData and panelTree — are placed upon the panelAll layout panel:

[DBPanel.java]

// package name and import statements omitted

public class DBPanel extends JPanel implements PropertyChangeListener, TableModelListener {

// declarations omitted for the sake of brevity [Please check download code] public DBPanel() {

JPanel panelAll = new JPanel(new GridLayout(0,1,5,5)); JPanel panelData = new JPanel(new GridLayout(0,1,5,5)); panelData.add(panelTable());

setPreferredSize(new Dimension(300, 450)); String[] s = { “”, “”, “”, “” }; mtm.populateTable(s);

addTableData();

panelAll.add(panelData);

JPanel panelTree = new JPanel(new GridLayout(0,1,5,5)); panelTree.add(treePanel());

panelAll.add(panelTree);

addTreeData(0);

add(panelAll);

setBackground(Color.white);

}

The addTableData() method populates the array of string values called s with the four different Cola attributes (Brand, Cost, Calories, and Size) and passes that array to the populateTable method for display. The addTree(int row) method allows users to add the Cola data to the row value passed into the method:

173

Chapter 4

public void addTableData() { String[] s = { “”, “”, “”, “” };

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

s[0]=tableData[i][0]; s[1]=tableData[i][1]; s[2]=tableData[i][2]; s[3]=tableData[i][3];

mtm.populateTable(s);

}

}

public void addTreeData(int row) {

root = new DefaultMutableTreeNode(“Cola Attributes”); tree = new JTree(root);

DefaultMutableTreeNode items;

items = new DefaultMutableTreeNode(“Cola “ + (row+1)); root.add(items);

items.add(new DefaultMutableTreeNode(“Brand= “ + tableData[row][0])); items.add(new DefaultMutableTreeNode(“Cost= “ + tableData[row][1])); items.add(new DefaultMutableTreeNode(“Calories= “ + tableData[row][2])); items.add(new DefaultMutableTreeNode(“Size= “ + tableData[row][3])); scrollPane.getViewport().add( tree );

tree.expandRow(0);

}

The panelTable() method creates a new MyTableModel object reference and adds it to a JTable object called tree, which in turn is placed inside a scroll pane component so that users can navigate up and down in the table when cola data attributes are added to the table component. The ListSelectionModel interface is implemented to maintain the tables’ row selection state. The addListSelectionListener method monitors the list so that changes to that list are reflected in the GUI representation:

public JPanel panelTable() {

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

mtm = new MyTableModel(); table = new JTable(mtm);

table.setPreferredScrollableViewportSize(new Dimension(250, 70)); JScrollPane scrollPane = new JScrollPane(table);

tablePanel.add(scrollPane);

table.setSelectionMode(ListSelectionModel.SINGLE_SELECTION); ListSelectionModel rowSM = table.getSelectionModel(); rowSM.addListSelectionListener(new ListSelectionListener() {

public void valueChanged(ListSelectionEvent e) { //Ignore extra messages.

if (e.getValueIsAdjusting()) return;

lsm = (ListSelectionModel)e.getSource(); if (lsm.isSelectionEmpty()) {

//no rows are selected } else {

selectedRow = lsm.getMinSelectionIndex();

174

Developing Effective User Interfaces with JFC

}

}

});

// titledBorder logic omitted for the sake of brevity

return tablePanel;

}

The treePanel() method establishes a new GridLayout manager so that a JTree structure can be embedded within a scroll pane, which will allow the user to vertically scroll up and down the tree structure. The BorderFactory class is implemented so that a compound border titled Tree Information frames the tree component:

public JPanel treePanel() {

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

scrollPane = new JScrollPane(); scrollPane.setVerticalScrollBarPolicy(

JScrollPane.VERTICAL_SCROLLBAR_ALWAYS); scrollPane.setPreferredSize(new Dimension(250, 150)); scrollPane.setBorder( BorderFactory.createCompoundBorder(BorderFactory.createCompoundBorder( BorderFactory.createTitledBorder(“Tree Information”), BorderFactory.createEmptyBorder(5,5,5,5)),

scrollPane.getBorder()));

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

tablePanel.add(scrollPane); return tablePanel;

}

public void propertyChange( PropertyChangeEvent e ) {} public void tableChanged(TableModelEvent e) {}

The MyTableModel class handles all of the table data for the six different Cola types through its method implementations. The setValueAt method stores an individual object value at a designated row and column value. The populateTable method reads in a string array and populates the table with those values. The fireTableDataChanged() method tells the application’s listeners that changes have been made to the table and need to be shown in the GUI representation:

class MyTableModel extends AbstractTableModel {

String[] columnNames= { “Brand”, “Cost”, “Calories”, “Size” }; private Object[][] data;

public int getColumnCount() { return columnNames.length; }

public int getRowCount() { return (data == null) ? 0 : data.length; }

public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return data[row][col]; }

// addRow() and deleteRow(int row) methods were omitted for sake of brevity

175

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