Chapter 01
Those that act as containers, such as JApplet, JFrame, JLayeredPane, JDesktopPane, and JInternalFrame, do not have models.
However, interactive components such as JButton, JTextField, and JTable do have models.
Some Swing components have more than one model, like JList.
Swing packages each component's view and controller into an object called a UI delegate. For this reason Swing’s underlying architecture is more accurately referred to as model delegate rather than model-view-controller.
Communication between both the model and the UI delegate is indirect, allowing more than one model to be associated with one UI delegate, and vice versa.
The skeleton of a Swing program proposed by another book, <Introduction to Java Programming>
import javax.swing.JLabel;
import javax.swing.JTextField;
import javax.swing.JFrame;
import java.awt.FlowLayout;
public class ShowFlowLayout extends JFrame {
public ShowFlowLayout() {
// Set FlowLayout, aligned left with horizontal gap 10
// and vertical gap 20 between components
setLayout (new FlowLayout(FlowLayout.LEFT, 10, 20));
// Add labels and text fields to the frame
add(new JLabel("First Name"));
add(new JTextField(8));
add(new JLabel("MI"));
add(new JTextField(1));
add(new JLabel("Last Name"));
add(new JTextField(8));
}
/** Main method */
public static void main(String[] args) {
ShowFlowLayout frame = new ShowFlowLayout();
frame.setTitle("ShowFlowLayout");
frame.setLocationRelativeTo(null); // Center the frame
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(200, 200);
frame.setVisible(true);
}
}
Chapter 02
JCOMPONENT
Properties
Simple property | A property for which there is no event firing associated with a change in its value is called a simple property. |
Bound property | A bound property is one for which PropertyChangeEvents are fired after the property changes value. |
Constrained property | A constrained property is one for which PropertyChangeEvents are fired before the property changes value. |
Change property | We use ChangeListeners to listen for ChangeEvents that get fired when these properties change state. A ChangeEvent only carries one piece of information with it: the source of the event. |
Client property | This feature allows properties to be added and removed at run-time. Client properties are also bound properties: when a client property changes, a PropertyChange-Event is dispatched to all registered PropertyChangeListeners. |
Size and positioning
setPreferredSize()
getPreferredSize()
setMinimumSize()
getMinimumSize()
setMaximumSize()
getMaximumSize()
setBounds()
getHeight()
getWidth()
getBounds()
getSize()
setAlignmentX(float f)
setAlignmentY(float f)
EVENT
In order to receive notification of events we need to register listeners with the source object. A listener is an implementation of any of the XXListener interfaces (where XX is an event type) defined in the java.awt.event, java.beans, and javax.swing.event packages.
Event-dispatching thread
By default all AWT and Swing-based applications start off with two threads. One is the main application thread which handles execution of the main() method. The other, referred to as the event-dispatching thread, is responsible for handling events, painting, and layout.
The code you write inside the body of an actionPerformed() method is executed within the event-dispatching thread automatically.
Associated with the event-dispatching thread is a FIFO (first in first out) queue of events called the system event queue.
Chapter 03
Frames n Panels
JFrame
The main container for a Swing-based application is JFrame. All objects associated with a JFrame are managed by its only child, an instance of JRootPane. When we add components to a JFrame, we don't directly add them to the JFrame. We have to specify into exactly which pane of the JFrame's JRootPane we want the component to be placed.
getContentPane().add(myComponent);
Introduction to Java Programming |
JDK 1.5 allows you to place components to the content pane by invoking a frame's add method. This new feature is called content pane delegation. |
The glassPane allows you to display components in front of an existing JFrame's contents. Though the glassPane does sit on top of the layeredPane, it is, by default, not visible. It can be set visible (show itself ) by calling:
getGlassPane().setVisible(true);
The menuBar does not exist by default.
The contentPane is, by default, an opaque JPanel. It can be set to any other component by calling:
setContentPane(myComponent);
JPanel
This is the simple container component commonly used to organize a group or groups of child components. JPanel is an integral part of JRootPane, its child components are managed by a layout manager.
Borders
Chapter 04
Chapter 05
Button
Each button class uses a model to store its state. We can access any button's model with AbstractButton's getModel() and setModel() methods. The ButtonModel interface is the template interface from which all button models are defined.
JButton is a basic push button. Any JRootPane container can define a default button using JRootPane's setDefaultButton() method (passing null will disable this feature).
We most often register an ActionListener with a button to receive ActionEvents from that button whenever it is clicked.
A typical inner class implementation
JButton myButton = new JButton();
ActionListener act = new ActionListener() {
public void actionPerformed(ActionEvent e) {
System.out.println("Swing is powerful!!");
}
};
myButton.addActionListener(act);
Chapter 18 Tables
JTable directly extends JComponent, and it implements interfaces:
- TableModelListener
- TableColumnModelListener
- ListSelectionListener
- CellEditorListener
- Scrollable
Each JTable has three models:
- TableModel
- TableColumnModel
- ListSelectionModel
With tables come two new kinds of events in Swing:
- TableModelEvent
- TableColumnModelEvent
Regular Java events apply to JTable as well. For instance, we can use MouseListeners to process double mouse clicks. Two events are also used for communication in TableColumnModel:
- ChangeEvents
- ListSelectionEvents
In all cases, if a specific model is not assigned in the constructor, JTable will create default implementations with its protected methods:
- createDefaultColumnModel()
- createDefaultDataModel()
- createDefaultSelectionModel()
It will do the same for each TableColumn renderer and editor, as well as for its JTableHeader, using:
- createDefaultEditors()
- createDefaultRenderers()
- createDefaultTableHeaders()
The TableModel interface
Instances of TableModel are responsible for storing a table's data in a two-dimensional structure such as a two-dimensional array or a Vector of Vectors.
TableModel supports the attachment of TableModelListeners which should be notified about changes to this model's data.
Each JTable uses one TableModel instance which can be assigned/retrieved using JTable's methods:
- setModel()
- getModel()
AbstractTableModel
AbstractTableModel is an abstract class that implements the TableModel interface. It provides default code for firingTableModelEventswith methods:
- fireTableRowsDeleted()
- fireTableCellUpdated()
- fireTableChanged()
It also manages all registered TableModelListeners in anEventListenerList.
Three methods need to be implemented in concrete subclasses:
- getRowCount()
- getColumnCount()
- getValueAt(int row, int column)
We are expected to use this class as a base for building our ownTableModelimplementations, rather than DefaultTableModel.
DefaultTableModel
DefaultTableModel is the default concrete TableModel implementation used byJTablewhen no model is specified in the constructor.
It uses a Vector of Vectors to manage its data.
This class implements three new event-dispatching methods, each taking a TableModelEvent as parameter:
- newDataAvailable()
- newRowsAdded()
- rowsRemoved()
TableColumn
TableColumn is the basic building block of JTable's visual representation, and it provides the main link between the JTable GUI and its model. The TableColumn class is responsible for managing column display in the actual JTable GUI. TableColumn does not extend java.awt.Component, and thus it is not a component.
An instance of TableColumn represents a specific column of data stored in a TableModel.
A TableColumn is represented graphically:
- column header renderer
- cell renderer
- cell editor(optionally)
TableColumn fires PropertyChangeEvents when any of thewidth,cellRenderer,headerRenderer, orheaderValue bound properties change. Thus we can add and remove PropertyChangeListeners to be notified of these changes. The corresponding property names are:
- COLUMN_WIDTH_PROPERTY
- COLUMN_RENDERER_PROPERTY
- HEADER_RENDERER_PROPERTY
- HEADER_VALUE_PROPERTY
The TableColumnModel interface
TableColumnModel controls how JTable displays its TableModel data.
The index of a TableColumn in a TableColumnModel's storage structure directly corresponds to its position in the JTable GUI.
- addColumn()
- removeColumn()
- moveColumn()
- getColumnCount()
- getColumns()
- getColumn()
- getColumnIndexAtX()
- getColumnIndex()
- setColumnMargin()
- getColumnMargin()
- getTotalColumnWidth()
TableColumnModel declares methods for controlling the selection of its TableColumns:
- setSelectionModel()
- getSelectionModel()
- setColumnSelectionAllowed()
- getColumnSelectionAllowed()
TableColumnModel also declares support for TableColumnModelListeners. Its implementations are expected to fire events:
TableColumnModelEvent | whenever a TableColumn is added, removed, or moved; |
ChangeEvent | whenever margin size is changed; |
ListSelectionEvent | whenever a change in column selection occurs. |
DefaultTableColumnModel
The following protected methods are provided to fire events:
- fireColumnAdded()
- fireColumnRemoved()
- fireColumnMoved()
- fireColumnSelectionChanged()
- fireColumnMarginChanged()
The TableCellRenderer interface
This interface describes the renderer used to display cell data in a TableColumn.
The sole defined method is getTableCellRendererComponent(), with parameters:
- JTable table
- Object value
- boolean isSelected
- boolean hasFocus
- int row
- int column
The row and column parameters refer to the location of data in the TableModel, not a cell location in the TableColumnModel.
DefaultTableCellRenderer
This is the concrete default implementation of the TableCellRenderer interface. DefaultTableCellRenderer extendsJLabel and is used as the default class-based renderer for Number, Icon, and Object data types.
The TableCellEditor interface
Each TableColumn has an associated TableCellEditor which can be assigned and retrieved with the methods:
- setCellEditor()
- getCellEditor()
The sole defined method is getTableCellEditorComponent(), with parameters:
- JTable table
- Object value
- boolean isSelected
- int row
- int column
The row and column parameters refer to the location of data in the TableModel, not a cell location in the TableColumnModel.
DefaultCellEditor
DefaultCellEditor is a concrete implementation of both the TableCellEditor interface and the TreeCellEditor interface. This editor is designed to return either a JTextField, JComboBox, or JCheckBox for cell editing.
The TableModelListener interface
TableModel's methods are used to add and remove TableModelListeners:
- addTableModelListener()
- removeTableModelListener()
TableModelEvent
This class consists of four properties, which are each accessible with typical get methods:
- int column
- int firstRow
- int lastRow
- int type
- TableModelEvent.INSERT
- TableModelEvent.DELETE
- TableModelEvent.UPDATE
The TableColumnModelListener interface
Five methods are declared in this interface and they must be defined by all implementations:
- columnAdded(TableColumnModelEvent)
- columnRemoved(TableColumnModelEvent)
- columnMoved(TableColumnModelEvent)
- columnMarginChanged(TableColumnModelEvent)
- columnSelectionChanged(ListSelectionEvent)
TableColumnModelEvent
A TableColumnModel fires a TableColumnModelEvent whenever a column move, removal, or addition occurs. The event source can be retrieved with getSource().
JTableHeader
JTableHeader extends JComponent and implements TableColumnModelListener.
This component is used internally by JTable. It can be retrieved with JTable'sgetTableHeader() method and assigned withsetTableHeader(). When a JTable is placed in a JScrollPane, a default JTableHeader corresponding to each column is added.
JTableHeader also maintains a reference to the TableColumn it represents as well as the JTable it is part of, using the tableColumn and table properties, respectively.
JTable selection
JTable supports two selection models: one for row selections and one for column selections. JTable also supports the selection of individual table cells.
Column selections are managed by a ListSelectionModel which is maintained by a TableColumnModel implementation, and row selections are managed by a ListSelectionModel which is maintained by JTable itself.
myJTable.getSelectionModel().setSelectedMode(ListSelectionModel.XX_SELECTION);
myJTable.getColumnModel().getSelectionModel().setSelectionMode(ListSelectionModel.XX_SELECTION);
JTable also provides control over whether individual cells can be selected with its cellSelectionEnabled property.
- getSelectedColumn()
- getSelectedRow()
- getSelectedColumns()
- getSelectedRows()
- getSelectedColumnCount()
- getSelectedRowCount()
- isColumnSelected()
- isRowSelected()
- isCellSelected()
- clearSelection()
- selectAll()
- addColumnSelectionInterval()
- addRowSelectionInterval()
- removeColumnSelectionInterval()
- removeRowSelectionInterval()
- setColumnSelectionInterval()
- setRowSelectionInterval()
When cell selection is enabled, JTable considers the columns and rows that contain selected cells as selected themselves (even though they aren’t highlighted). For example, if cells (1,5) and (3,6) are selected with row and column selection enabled and cell selection enabled, getSelectedColumns() will return {5,6} and getSelectedRows() will return {1,3}.
Determine by the location where MouseEvent occurres:
myJTable.addMouseListener(
new MouseAdapter() {
public void mouseClicked(MouseEvent e) {
if (e.getClickCount() == 2) {
Point origin = e.getPoint();
int row = myJTable.rowAtPoint(origin);
int column = myJTable.columnAtPoint(origin);
if (row == -1 || column == -1)
return; // no cell found
else
// Do something cell-specific
}
}
}
);