Professional Java.JDK.5.Edition (Wrox)
.pdfChapter 4
public void setValueAt(Object value, int row, int col) { data[row][col] = value;
}
The populateTable method receives a string array of table data that relates to the Cola button selection so that it can be added to the JTable component for observation. Once the table has been populated, then the fireTableDataChanged() method is invoked so that these table changes are updated in the GUI view:
public void populateTable(String[] s) {
// if data exists in table, rewrite table for new entry int rowCount = getRowCount();
if (rowCount != 0) {
//add another row Object[][] temp = data;
data = new Object[rowCount+1][getColumnCount()];
//copy old items into new structure
for (int i=0; i < temp.length; i++) { data[i][0] = temp[i][0]; data[i][1] = temp[i][1]; data[i][2] = temp[i][2]; data[i][3] = temp[i][3];
}
for (int i=0; i < getColumnCount(); i++) setValueAt(s[i], rowCount-1, i);
} else {
data = cData;
for (int i=0; i < getColumnCount(); i++) setValueAt(s[i], 0, i);
}
fireTableDataChanged();
}
}
public void setRow(int row) { table.setRowSelectionInterval(row, row);
}
// main method omitted for the sake of brevity
}
Figure 4-8 represents the GridLayoutPanel application defined in the source code above. When users click on the Java 2D button images, proper Cola values will be highlighted in the Swing components on the right side of the GUI display.
176
Developing Effective User Interfaces with JFC
Figure 4-8
GridBagLayout
The GridBagLayout manager manages its components both vertically and horizontally by maintaining a rectangular grid of cells in its display area. Components are manipulated through constraint parameters using the GridBagConstraints class. These constraints specify where a component’s display area should be positioned on the grid and its size using minimum and preferred size attributes. The constructor methods for the GridBagLayout manager are shown in the method summary table that follows.
Method |
Description |
public GridBagLayout() |
No parameters |
The table below outlines the different instance variables that can be implemented with the GridBagLayout manager. These variables can be implemented interchangeably to satisfy an application’s visual requirements.
Instance Variables |
Description |
|
|
gridx, gridy |
The gridx and gridy instance variables specify the cells con- |
|
taining the leading corner of the component’s display area, |
|
where the cell at the origin of the grid has address x = 0 |
|
degrees and y = 0 degrees. For applications that have horizon- |
|
tal left-to-right layouts, the leading corner is on the upper left. |
|
For applications that have horizontal right-to-left layouts, the |
|
leading corner is on the upper right. |
|
|
|
Table continued on following page |
177
Chapter 4
Instance Variables |
Description |
|
|
weightx, weighty |
The weightx and weighty instance variables are used to |
|
determine how to distribute space for resizing. All components |
|
are placed together in the middle of a container unless a |
|
weightx or weighty value is specified. The GridBagLayout |
|
manager appends additional space between its cells and the |
|
container edges when the default weight is initialized to zero. |
insets |
The insets instance variable specifies the component’s |
|
padding, which amounts to the minimum space available |
|
between the component and the display area edges. |
fill |
The fill instance variable is implemented when the compo- |
|
nent’s display area is larger than the component’s requested |
|
size to determine whether (and how) to resize the component. |
|
GridBagConstraints.NONE (the default) |
|
GridBagConstraints.HORIZONTAL — enables the component |
|
to fill its display area horizontally, not vertically |
|
GridBagConstraints.VERTICAL — allows the component to |
|
fill its display area vertically, not horizontally |
|
GridBagConstraints.BOTH — allows the component to fill its |
|
display area both vertically and horizontally |
|
|
The following GridBagLayout example applies both the Command and Visitor patterns to handle user events and message generation from Swing component activities. Figure 4-9 provides a model of the application and the component distribution on the GridBagLayout and their listeners.
The GridBagLayoutPanel application will incorporate the Command and Visitor patterns to handle button requests for answers to the questions selected by the user in the different question components. Some of the benefits and shortcomings of these patterns are shown in the following table.
Pattern |
Benefits |
Consequences |
Visitor |
Separates operations from the |
|
objects that perform operations |
|
on it. Objects of the primary type |
|
accept the visitor and then call the |
|
visitor’s dynamically bound |
|
method in a process referred to |
|
as double dispatch. |
|
Adding new operations is |
|
facilitated, no need for |
|
recompilation. |
Difficult to maintain
Forces you to provide public operations that access internal state data, which may break encapsulation
178
Developing Effective User Interfaces with JFC
GridBagLayout
FlowLayout: topPanel
JLabel |
JComboBox |
Command pattern: execute()
JScrollPane
Visitor pattern:
Generate random message in displayMessage()
GridLayout: radioPanel
ButtonGroup
RadioListener
MouseListener
JLabel
Figure 4-9
The GridBagLayoutPanel class incorporates the GridBagLayout manager, which allows for the placement of GUI components in a grid formation of rows and columns. The width and height of the rows and columns do not necessarily have to be the same size throughout a panel display, but this sample application maintains consistency across rows and columns for its GUI components:
[GridBagLayoutPanel.java]
// package name and import statements omitted
public class GridBagLayoutPanel extends JPanel implements ActionListener {
// declarations omitted for the sake of brevity [Please check download code]
The GridBagLayoutPanel constructor method declares and initializes the Swing components used for the fortune teller application. First a JcomboBox component is created with a list of questions that can be selected from the drop-down box. Next, a group of radio buttons is created, grouped together, and registered to the application using the RadioListener class. Those radio buttons are grouped vertically and appended to the radioPanel. Both the drop-down list and the radio buttons are appended to the topPanel display. Lastly, a list of questions is generated and added to a JScrollPane component and registered with a MouseListener to generate fortunes when a user double-clicks a question in the list:
public GridBagLayoutPanel() {
setSize(200, 150);
cbQuestion = new JComboQuestion(); cbQuestion.addActionListener(this);
label = new JLabel(“Question: “); label.setFont(messageFont);
RadioListener radioListener = new RadioListener();
179
Chapter 4
question1Button.setMnemonic(‘1’);
question2Button.setMnemonic(‘2’);
question3Button.setMnemonic(‘3’);
question1Button.addActionListener(radioListener);
question2Button.addActionListener(radioListener);
question3Button.addActionListener(radioListener); ButtonGroup group = new ButtonGroup(); group.add(question1Button); group.add(question2Button); group.add(question3Button);
JPanel radioPanel = new JPanel(); radioPanel.setLayout(new GridLayout(0, 1)); radioPanel.add(question1Button); radioPanel.add(question2Button); radioPanel.add(question3Button);
String[] data = {“Will the Yankees win the pennant?”, “Will the Giants win the Super Bowl?”, “Will the Rangers win the Stanley Cup?”};
In the code snippet below, a JList component is instantiated and attached to a mouse listener so that user clicks are detected upon that list. If a user double-clicks a list item, then the displayMessage() method will be invoked with a randomly generated fortune related to the question selected by the user in the list:
final JList list = new JList(data);
MouseListener mouseListener = new MouseAdapter() { public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
logger.info(“Double clicked: “ + list.locationToIndex(e.getPoint())); displayMessage();
}
}
};
list.setFont(listFont);
list.addMouseListener(mouseListener); JScrollPane listScroller = new JScrollPane(list);
listScroller.setPreferredSize(new Dimension(100, 125)); listScroller.setBorder(new TitledBorder(“Double-click query for fortune”)); topPanel.add(label);
topPanel.add(cbQuestion);
topPanel.add(radioPanel);
topPanel.setBorder(new TitledBorder(“Question components”));
messageText = new JLabel(“Please pick a question...”); messageText.setFont(messageFont); results.add(messageText); results.setPreferredSize(new Dimension(400, 50));
results.setBorder(BorderFactory.createLineBorder (Color.blue, 2)); results.setBackground(Color.yellow);
The following code segment demonstrates how the components are rendered using the GridBagLayout manager. The GridBagConstraints class is instantiated so that constraints can be specified for the GUI components in the application using the GridBagLayout manager:
180
Developing Effective User Interfaces with JFC
setLayout(new GridBagLayout());
GridBagConstraints c = new GridBagConstraints(); c.gridx = 0;
c.gridy = 0; c.weightx = 0.5;
c.insets = new Insets( 2, 2, 2, 2 ); c.fill = GridBagConstraints.BOTH; add(topPanel, c);
c.gridy = 1; c.weightx = 0.5; c.gridwidth = 1;
c.fill = GridBagConstraints.HORIZONTAL; add(listScroller, c);
c.gridx = 0; c.gridy = 2; c.weightx = 0.0;
c.insets = new Insets( 50, 50, 0, 0 ); c.fill = GridBagConstraints.NONE; add(results, c);
}
public void actionPerformed(ActionEvent e) { JComboQuestion cb = (JComboQuestion)e.getSource(); Command obj = (Command)e.getSource();
String question = (String)cb.getSelectedItem();
if (!question.equals(“Pick a question?”)) { obj.execute();
}
}
The JComboQuestion class implements the Command pattern interface so that the GridBagLayoutPanel class can invoke its execute() method when a user clicks the combo box affiliated with a question list reference qbQuestion. The Command pattern increases reuse by decoupling the interface from the implementation, which means that all GUI components in the GridBagLayoutPanel class can use the public execute() method interface to serve as a gateway to private implementations associated with them:
class JComboQuestion extends JComboBox implements Command {
public JComboQuestion() { this.addItem(“Pick a question?”); this.addItem(“Will I pass my class?”);
this.addItem(“Will my candidate win the election?”); this.addItem(“Will I grow up to be a doctor?”); setFont(messageFont);
}
public void execute() { displayMessage();
}
}
181
Chapter 4
The displayMessage() method selects a random number between 1 and 3 and uses that number to generate a fortune using the Visitor pattern. The Visitor pattern implementation polymorphically determines the proper accept method to call during operations:
public void displayMessage() { MessageText mt = new MessageText();
int number = (int) (Math.random () * 3 + 1); switch(number) {
case 1: ((FortuneTeller)new Message1()).accept(mt); break; case 2: ((FortuneTeller)new Message2()).accept(mt); break; case 3: ((FortuneTeller)new Message3()).accept(mt); break;
}
messageText.setFont(messageFont);
messageText.setText(mt.toString());
results.add(messageText);
}
public interface Command { public void execute();
}
class RadioListener implements ActionListener { public void actionPerformed(ActionEvent e) {
displayMessage();
}
}
static public void main(String argv[]) { JFrame frame = new JFrame(“GridBagLayout”);
frame.addWindowListener(new WindowAdapter() {
public void windowClosing(WindowEvent e) {System.exit(0);}
});
frame.getContentPane().add(new GridBagLayoutPanel(), BorderLayout.CENTER); frame.pack();
frame.setVisible(true);
}
}
Figure 4-10 shows the visual representation of the GridLayoutPanel application. Random fortunes will be generated by the Visitor pattern implementation when the user selects a question from the different Swing components.
182
Developing Effective User Interfaces with JFC
Figure 4-10
SpringLayout
The SpringLayout manager lays out its Container components according to user-specified constraint parameters. Each constraint, represented by a Spring object, controls the vertical or horizontal distance between two component edges. The edges can belong to any child of the container, or to the container itself.
The SpringLayout manager does not set the location of its components automatically like some of the other layout managers. Component locations need to be initialized through constraint parameters so that minimum, maximum, and preferred lengths can be contained and bound. The constructor methods for the SpringLayout manager are shown in the method summary table below.
Method |
Description |
SpringLayout() |
Constructor (no parameters) |
The following are some of the fields used to describe the constraints for component placement.
Field |
Description |
|
|
static String EAST |
Right edge of component |
static String NORTH |
Top edge of component |
static String SOUTH |
Bottom edge of component |
static String WEST |
Left edge of component |
|
|
183
Chapter 4
The following SpringLayout example allows users to generate log entries for their triathlon events using a simple form display. Simple checks will be performed on the data prior to submission to ensure that all of the relevant data has been entered by the user. When the user saves that event, it will be stored in a JTable component for review. Figure 4-11 demonstrates what the SpringLayout application will look like. Only one tabbed panel will be on display at a time, which will be dictated by the user navigations from the button components at the bottom of the application.
SpringLayout |
|
|
|
|
|
JTabbedPane |
JTabbedPane |
|
|
|
|
eventPanel |
|
SpringLayout: panelInput |
|||
|
JLabel |
|
JTextfield |
|
|
|
JLabel |
JCombobox |
JLabel |
JCombobox |
|
JTable |
JLabel |
JSpinner |
|
JLabel |
JCombobox |
|
|
JTextArea |
|
||
JButton |
|
JButton |
|
JButton |
|
(add event) |
|
(save) |
|
(cancel) |
|
Command pattern: execute() |
Command pattern: execute() |
||||
Figure 4-11 |
|
|
|
|
|
The following code segment outlines in code how the model in Figure 4-11 will be realized:
[SpringLayoutPanel.java]
// package name and import statements omitted
public class SpringLayoutPanel extends JPanel implements ActionListener {
// declarations omitted for the sake of brevity [Please check download code] public SpringLayoutPanel(String name) {
initComponents();
}
private void initComponents() { tabPanel = new JTabbedPane();
eventPanel = new JPanel(); eventPanel.setLayout(new BorderLayout());
eventPanel.setPreferredSize(new Dimension(350, 400)); eventPanel.setToolTipText(“Event”);
184
Developing Effective User Interfaces with JFC
eventPanel.add(“Center”, EventPanel());
tabPanel.addTab(“Triathlon Record Log”, eventPanel); add(tabPanel, BorderLayout.CENTER);
}
The EventPanel() method initializes many of the Swing components in the SwingLayoutPanel application and combines BorderLayout and GridLayout manager panels to obtain its visualization needs:
public JPanel EventPanel() {
JPanel ePanel = new JPanel(new GridLayout(0, 1, 5, 5)); ePanel.setMaximumSize(new Dimension(350, 400)); ePanel.setMinimumSize(new Dimension(350, 400)); ePanel.setPreferredSize(new Dimension(350, 400));
eventPanel = new JPanel(); eventButtonPanel = new JPanel(); addEventButton = new JAddEventButton();
eventPanel.setLayout(new BorderLayout()); eventPanel.setMinimumSize(new Dimension(350, 400)); eventPanel.setPreferredSize(new Dimension(350, 400));
gridPanel = new JPanel(new GridLayout(0, 1, 5, 5)); gridPanel.add(panelTable());
eventButtonPanel.setLayout(new GridLayout(1, 2));
addEventButton.setText(“Add New Event”); addEventButton.setToolTipText(“Add New Event”); addEventButton.addActionListener(this); eventButtonPanel.add(addEventButton); eventButtonPanel.setPreferredSize(new Dimension(350, 30)); eventPanel.add(eventButtonPanel, BorderLayout.SOUTH); eventPanel.add(gridPanel, BorderLayout.NORTH);
String[] s = { “”, “”, “”, “” }; mtm.populateTable(s);
ePanel.add(eventPanel);
return ePanel;
}
The panelTable method implements a GridLayout manager to accommodate the inclusion of a JTable component that will store the different triathlon log entries. A ListSelectionListener is instantiated to handle user events that affect the table:
public JPanel panelTable() {
JPanel tablePanel = new JPanel(new GridLayout(0, 1, 5, 5));
mtm = new MyTableModel();
185