<!-- [if !mso]> <style> v/:* {behavior:url(#default#VML);} o/:* {behavior:url(#default#VML);} w/:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]-->
Swing 2 Edito1
1. Swing 的特性
<1> Pluggable Look-and-Feels 可插入的实感外观, 可以动态的去替换。
<2> Lightweight Components 轻量级组件
<3> Swing 提供更广泛的组件
<4> Swing 可以替换它的插入效果. 通过替换Border
<5> Swing 组件有tooltips
2. UIManager.setLookAndFeel (lnfName);
SwingUtilities.updateComponentTreeUI ( frame );
JTable 学习
1.
JTable(Object[][] rowData, Object[] columnNames)
JTable(Vector rowData, Vector columnNames)
使用以上两个构造函数的不利点:
<1> 单元格都可以编辑
<2> By default, all columns in a table start out with equal width, and the columns automatically fill the entire width of the table,When the table becomes wider or narrower (which might happen when the user resizes the window containing the table), all the column widths change appropriately.
默认,所有的列都是相当的宽度,会自动填充整个表格的宽度 . 当调整表格的宽度,所有的列会自动的改变宽度 .
2.
TableColumn column = null;
for (int i = 0; i < 5; i++) {
column = table.getColumnModel().getColumn(i);
if (i == 2) {
column.setPreferredWidth(100); //third column is bigger
} else {
column.setPreferredWidth(50);
}
}
3.
TableColumn
supplies getter and setter methods for the minimum, preferred, and maximum widths of a column, as well as a method for getting the current width. For an example of setting cell widths based on an approximation of the space needed to draw the cells' contents, see theinitColumnSizes
method inTableRenderDemo.java
.
4.
User Selections
<1> The user can select a contiguous range of rows or an arbitrary set of rows
用户可以选择连续变化的行或者任意的行
<2>Row Selection
Column Selection
Cell Selection
5.
Creating a Table Model
6.
Listening for Data Changes
<1>A table model can have a set of listeners that are notified whenever the table data changes. Listeners are instances of TableModelListener
7.
Firing Data Change Events
Method | Change |
fireTableCellUpdated | Update of specified cell. |
fireTableRowsUpdated | Update of specified rows |
fireTableDataChanged | Update of entire table (data only). |
fireTableRowsInserted | New rows inserted. |
fireTableRowsDeleted | Existing rows Deleted |
fireTableStructureChanged | Invalidate entire table, both data and structure |
|
|
8.
Concepts: Editors and Renderers
9.
Using Custom Renderers
<1>You can set a type-specific cell renderer using the JTable
method setDefaultRenderer
. To specify that cells in a particular column should use a renderer, you use the TableColumn
method setCellRenderer
. You can even specify a cell-specific renderer by creating a JTable
subclass
<2>If extending DefaultTableCellRenderer
is insufficient, you can build a renderer using another superclass. The easiest way is to create a subclass of an existing component, making your subclass implement the TableCellRenderer
interface
<3> In the snapshot of TableDialogEditDemo
, the renderer used for Favorite Color cells is a subclass of JLabel
called ColorRenderer
. Here are excerpts from ColorRenderer.java
that show how it is implemented.
public class ColorRenderer extends JLabel
implements TableCellRenderer {
...
public ColorRenderer(boolean isBordered) {
this.isBordered = isBordered;
setOpaque(true); //MUST do this for background to show up.
}
public Component getTableCellRendererComponent(
JTable table, Object color,
boolean isSelected, boolean hasFocus,
int row, int column) {
Color newColor = (Color)color;
setBackground(newColor);
if (isBordered) {
if (isSelected) {
...
//selectedBorder is a solid border in the color
//table.getSelectionBackground().
setBorder(selectedBorder);
} else {
...
//unselectedBorder is a solid border in the color
//table.getBackground().
setBorder(unselectedBorder);
}
}
setToolTipText(...); //Discussed in the following section
return this;
}
}
Here is the code from TableDialogEditDemo.java
that registers a ColorRenderer
instance as the default renderer for all Color
data:
table.setDefaultRenderer(Color.class, new ColorRenderer(true));
<4> To specify a cell-specific renderer, you need to define a JTable
subclass that overrides the getCellRenderer
method. For example, the following code makes the first cell in the first column of the table use a custom renderer:
TableCellRenderer weirdRenderer = new WeirdRenderer();
table = new JTable(...) {
public TableCellRenderer getCellRenderer(int row, int column) {
if ((row == 0) && (column == 0)) {
return weirdRenderer;
}
// else...
return super.getCellRenderer(row, column);
}
};
Specifying Tool Tips for Cells
<1> By default, the tool tip text displayed for a table cell is determined by the cell's renderer. However, sometimes it can be simpler to specify tool tip text by overriding JTable
's implementation of the getToolTipText(MouseEvent)
method . This section shows you how to use both techniques.
<2>To add a tool tip to a cell using its renderer, you first need to get or create the cell renderer. Then, after making sure the rendering component is a JComponent
, invoke the setToolTipText
method on it
<3>JTable table = new JTable(new MyTableModel()) {
//Implement table cell tool tips.
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int rowIndex = rowAtPoint(p);
int colIndex = columnAtPoint(p);
int realColumnIndex = convertColumnIndexToModel(colIndex);
if (realColumnIndex == 2) { //Sport column
tip = "This person's favorite sport to "
+ "participate in is: "
+ getValueAt(rowIndex, colIndex);
} else if (realColumnIndex == 4) { //Veggie column
TableModel model = getModel();
String firstName = (String)model.getValueAt(rowIndex,0);
String lastName = (String)model.getValueAt(rowIndex,1);
Boolean veggie = (Boolean)model.getValueAt(rowIndex,4);
if (Boolean.TRUE.equals(veggie)) {
tip = firstName + " " + lastName
+ " is a vegetarian";
} else {
tip = firstName + " " + lastName
+ " is not a vegetarian";
}
} else { //another column
//You can omit this part if you know you don't
//have any renderers that supply their own tool
//tips.
tip = super.getToolTipText(e);
}
return tip;
}
...
}
11
Specifying Tool Tips for Column Headers
<1> You can add a tool tip to a column header by setting the tool tip text for the table's JTableHeader
. Often, different column headers require different tool tip text. You can change the text by overriding the table header's getToolTipText
method. Alternately, you can invoke TableColumn.setHeaderRenderer
to provide a custom renderer for the header.
<2> The following code implements the tool tips. Basically, it creates a subclass of JTableHeader
that overrides the getToolTipText(MouseEvent)
method so that it returns the text for the current column. To associate the revised table header with the table, the JTable
method createDefaultTableHeader
is overridden so that it returns an instance of the JTableHeader
subclass.
protected String[] columnToolTips = {
null, // "First Name" assumed obvious
null, // "Last Name" assumed obvious
"The person's favorite sport to participate in",
"The number of years the person has played the sport",
"If checked, the person eats no meat"};
...
JTable table = new JTable(new MyTableModel()) {
...
//Implement table header tool tips.
protected JTableHeader createDefaultTableHeader() {
return new JTableHeader(columnModel) {
public String getToolTipText(MouseEvent e) {
String tip = null;
java.awt.Point p = e.getPoint();
int index = columnModel.getColumnIndexAtX(p.x);
int realIndex =
columnModel.getColumn(index).getModelIndex();
return columnToolTips[realIndex];
}
};
}
};
12
Sorting and Filtering
<1> Table sorting and filtering is managed by a sorter object. The easiest way to provide a sorter object is to set autoCreateRowSorter bound property to true:
JTable table = new JTable();
table.setAutoCreateRowSorter(true);
This action defines a row sorter that is an instance of javax.swing.table.TableRowSorter . This provides a table that does a simple locale-specific sort when the user clicks on a column header. This is demonstrated in TableSortDemo.java , as seen in this screen shot:
To have more control over sorting, you can construct an instance of TableRowSorter and specify that it is the sorter object for your table.
TableRowSorter<TableModel> sorter
= new TableRowSorter<TableModel>(table.getModel());
table.setRowSorter(sorter);
<2> When a table uses a sorter, the data the users sees may be in a different order than that specified by the data model, and may not include all rows specified by the data model. The data the user actually sees is known as the view , and has its own set of coordinates. JTable provides methods that convert from model coordinates to view coordinates — convertColumnIndexToView and convertRowIndexToView — and that convert from view coordinates to model coordinates — convertColumnIndexToModel and convertRowIndexToModel .
NOTE: When using a sorter, always remember to translate cell coordinates
13
Using a Combo Box as an Editor
14
Using Other Editors
<1> What if you want to specify an editor other than a text field, check box, or combo box? As DefaultCellEditor
does not support other types of components, you must do a little more work. You need to create a class that implements the TableCellEditor
interface. The AbstractCellEditor
class is a good superclass to use. It implements TableCellEditor
's superinterface, CellEditor
, saving you the trouble of implementing the event firing code necessary for cell editors
<2>Your cell editor class needs to define at least two methods — getCellEditorValue
and getTableCellEditorComponent
. The getCellEditorValue
method, required by CellEditor
, returns the cell's current value. The getTableCellEditorComponent
method, required by TableCellEditor
, should configure and return the component that you want to use as the editor.
<3>Here is the code, taken from ColorEditor.java
, that implements the cell editor.
public class ColorEditor extends AbstractCellEditor
implements TableCellEditor,
ActionListener {
Color currentColor;
JButton button;
JColorChooser colorChooser;
JDialog dialog;
protected static final String EDIT = "edit";
public ColorEditor() {
button = new JButton();
button.setActionCommand(EDIT);
button.addActionListener(this);
button.setBorderPainted(false);
//Set up the dialog that the button brings up.
colorChooser = new JColorChooser();
dialog = JColorChooser.createDialog(button,
"Pick a Color",
true,
//modal
colorChooser,
this,
//OK button handler
null); //no CANCEL button handler
}
public void actionPerformed(ActionEvent e) {
if (EDIT.equals(e.getActionCommand())) {
//The user has clicked the cell, so
//bring up the dialog.
button.setBackground(currentColor);
colorChooser.setColor(currentColor);
dialog.setVisible(true);
fireEditingStopped(); //Make the renderer reappear.
} else { //User pressed dialog's "OK" button.
currentColor = colorChooser.getColor();
}
}
//Implement the one CellEditor method that AbstractCellEditor doesn't.
public Object getCellEditorValue() {
return currentColor;
}
//Implement the one method defined by TableCellEditor.
public Component getTableCellEditorComponent(JTable table,
Object value,
boolean isSelected,
int row,
int column) {
currentColor = (Color)value;
return button;
}
}
As you can see, the code is pretty simple. The only part that is a bit tricky is the call to fireEditingStopped
at the end of the editor button's action handler. Without this call, the editor would remain active, even though the modal dialog is no longer visible. The call to fireEditingStopped
lets the table know that it can deactivate the editor, letting the cell be handled by the renderer again.
15
Using an Editor to Validate User-Entered Text
16
Printing
JTextComponent
<!-- [if !mso]> <style> v/:* {behavior:url(#default#VML);} o/:* {behavior:url(#default#VML);} w/:* {behavior:url(#default#VML);} .shape {behavior:url(#default#VML);} </style> <![endif]--><!-- [if gte mso 9]><xml> <w:WordDocument> <w:View>Normal</w:View> <w:Zoom>0</w:Zoom> <w:PunctuationKerning/> <w:DrawingGridVerticalSpacing>7.8 磅</w:DrawingGridVerticalSpacing> <w:DisplayHorizontalDrawingGridEvery>0</w:DisplayHorizontalDrawingGridEvery> <w:DisplayVerticalDrawingGridEvery>2</w:DisplayVerticalDrawingGridEvery> <w:ValidateAgainstSchemas/> <w:SaveIfXMLInvalid>false</w:SaveIfXMLInvalid> <w:IgnoreMixedContent>false</w:IgnoreMixedContent> <w:AlwaysShowPlaceholderText>false</w:AlwaysShowPlaceholderText> <w:Compatibility> <w:SpaceForUL/> <w:BalanceSingleByteDoubleByteWidth/> <w:DoNotLeaveBackslashAlone/> <w:ULTrailSpace/> <w:DoNotExpandShiftReturn/> <w:AdjustLineHeightInTable/> <w:BreakWrappedTables/> <w:SnapToGridInCell/> <w:WrapTextWithPunct/> <w:UseAsianBreakRules/> <w:DontGrowAutofit/> <w:UseFELayout/> </w:Compatibility> <w:BrowserLevel>MicrosoftInternetExplorer4</w:BrowserLevel> </w:WordDocument> </xml><![endif]--><!-- [if gte mso 9]><xml> <w:LatentStyles DefLockedState="false" LatentStyleCount="156"> </w:LatentStyles> </xml><![endif]--><!-- [if gte mso 10]> <style> /* Style Definitions */ table.MsoNormalTable {mso-style-name:普通表格; mso-tstyle-rowband-size:0; mso-tstyle-colband-size:0; mso-style-noshow:yes; mso-style-parent:""; mso-padding-alt:0cm 5.4pt 0cm 5.4pt; mso-para-margin:0cm; mso-para-margin-bottom:.0001pt; mso-pagination:widow-orphan; font-size:10.0pt; font-family:"Times New Roman"; mso-ansi-language:#0400; mso-fareast-language:#0400; mso-bidi-language:#0400;} </style> <![endif]-->
The abstract base class from which all the different L&Fs extend. It defines a number of static convenience methods, as well as some abstract methods required by every L&F.
An L&F is responsible for defining a set of default properties. UIDefaults is a Hashtable subclass that holds these properties. The properties include UIClassID to ComponentUI subclass mappings (e.g., "TreeUI" to MetalTreeUI) as well as lower-level defaults, such as colors and fonts.
UIDefaults.ActiveValue and UIDefaults.LazyValue
These inner interfaces of UIDefaults enable some optimizations for resource values.
This is an empty interface (like Serializable or Cloneable) used to tag property values. It allows values defined by the L&F to be distinguished from values set by the user, as described in Section 26.3.5 later in this chapter.
If you've ever changed the L&F of a Swing program at runtime, you're probably already familiar with this class. UIManager is responsible for tracking a global view of the L&Fs available in an application. It keeps track of the currently installed L&F and provides a mechanism to change the L&F. All of its methods are static, but it does provide a mechanism that allows multiple applets within a single virtual machine to use different L&Fs.
This inner class is used to describe available L&Fs without actually having to load the L&F classes. UIManager uses this class to provide a list of available L&Fs.
This is the base class common to all UI delegates. It defines all of the methods related to painting and sizing that the different delegate subclasses must implement.
You're certainly familiar with this class by now 梚t's the base class for all of the Swing components. We include it in this diagram to show that at any time, each JComponent has a reference to a single ComponentUI. ComponentUI objects may, however, be shared by multiple components. JComponent was covered in gory detail back in Chapter 3 .