The Java Tutorials have been written for JDK 8.Java教程是为JDK 8编写的。Examples and practices described in this page don't take advantage of improvements introduced in later releases and might use technology no longer available.本页中描述的示例和实践没有利用后续版本中引入的改进,并且可能使用不再可用的技术。See Java Language Changes for a summary of updated language features in Java SE 9 and subsequent releases.有关Java SE 9及其后续版本中更新的语言特性的摘要,请参阅Java语言更改。
See JDK Release Notes for information about new features, enhancements, and removed or deprecated options for all JDK releases.有关所有JDK版本的新功能、增强功能以及已删除或不推荐的选项的信息,请参阅JDK发行说明。
With the 使用JTable
class you can display tables of data, optionally allowing the user to edit the data. JTable
类,您可以显示数据表,并允许用户编辑数据。JTable
does not contain or cache data; it is simply a view of your data. 不包含或缓存数据;它只是一个数据视图。Here is a picture of a typical table displayed within a scroll pane:以下是滚动窗格中显示的典型表格的图片:
The rest of this section shows you how to accomplish some common table-related tasks. 本节的其余部分将向您展示如何完成一些常见的表相关任务。Here are the topics this section covers:本节涵盖的主题如下:
Click the Launch button to run 单击启动按钮,使用Java™Web启动运行SimpleTableDemo
using Java™ Web Start (download JDK 7 or later). SimpleTableDemo
(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
Click the cell that contains "Snowboarding".单击包含“单板滑雪”的单元格。
The entire first row is selected, indicating that you have selected Kathy Smith's data. 选择整个第一行,表示您已选择Kathy Smith的数据。A special highlight indicates that the "Snowboarding" cell is editable. 一个特别的突出显示表示“单板滑雪”单元格是可编辑的。Generally, you begin editing a text cell by double-clicking it.通常,您可以通过双击文本单元格来开始编辑。
Position the cursor over "First Name". 将光标放在“名字”上。Now press the mouse button and drag to the right.现在按下鼠标按钮并向右拖动,如您所见,用户可以重新排列表中的列。
As you can see, users can rearrange columns in tables.
Position the cursor just to the right of a column header. 将光标放置在列标题的右侧。Now press the mouse button and drag to the right or left.现在按下鼠标按钮并向右或向左拖动。
The column changes size, and the other columns adjust to fill the remaining space.列将更改大小,其他列将调整以填充剩余空间。
The table in SimpleTableDemo.java
declares the column names in a String array:SimpleTableDemo.java
中的表声明字符串数组中的列名:
String[] columnNames = {"First Name", "Last Name", "Sport", "# of Years", "Vegetarian"};
Its data is initialized and stored in a two-dimensional Object array:其数据被初始化并存储在二维对象数组中:
Object[][] data = { {"Kathy", "Smith", "Snowboarding", new Integer(5), new Boolean(false)}, {"John", "Doe", "Rowing", new Integer(3), new Boolean(true)}, {"Sue", "Black", "Knitting", new Integer(2), new Boolean(false)}, {"Jane", "White", "Speed reading", new Integer(20), new Boolean(true)}, {"Joe", "Brown", "Pool", new Integer(10), new Boolean(false)} };
Then the Table is constructed using these data and columnNames:然后使用这些数据和列名构建表:
JTable table = new JTable(data, columnNames);
There are two 有两个JTable
constructors that directly accept data (SimpleTableDemo
uses the first):JTable
构造函数直接接受数据(SimpleTableDemo
使用第一个):
JTable(Object[][] rowData, Object[] columnNames)
JTable(Vector rowData, Vector columnNames)
The advantage of these constructors is that they are easy to use. However, these constructors also have disadvantages:这些构造函数的优点是易于使用。然而,这些构造器也有缺点:
Boolean
data, the table can display the data in a check box. Boolean
数据,则该表可以在复选框中显示数据。JTable
constructors listed previously, your Boolean
data is displayed as a string. JTable
构造函数中的任何一个,则Boolean
数据将显示为字符串。Vegetarian
column of the previous figure.Vegetarian
栏中看到这种差异。If you want to get around these restrictions, you need to implement your own table model, as described in Creating a Table Model.如果要绕过这些限制,需要实现自己的表模型,如创建表模型中所述。
Here is typical code for creating a scroll pane that serves as a container for a table:下面是创建用作表容器的滚动窗格的典型代码:
JScrollPane scrollPane = new JScrollPane(table); table.setFillsViewportHeight(true);
The two lines in this snippet do the following:此代码段中的两行执行以下操作:
JScrollPane
constructor is invoked with an argument that refers to the table object. JScrollPane
构造函数使用引用表对象的参数调用。JTable.setFillsViewportHeight
is invoked to set the fillsViewportHeight
property. JTable.setFillsViewportHeight
来设置fillsViewportHeight
属性。true
the table uses the entire height of the container, even if the table doesn't have enough rows to use the whole vertical space. true
,则表将使用容器的整个高度,即使表没有足够的行来使用整个垂直空间。The scroll pane automatically places the table header at the top of the viewport. 滚动窗格会自动将表格标题放置在视口的顶部。The column names remain visible at the top of the viewing area when the table data is scrolled.滚动表数据时,列名在查看区域的顶部保持可见。
If you are using a table without a scroll pane, then you must get the table header component and place it yourself. 如果使用的表没有滚动窗格,则必须获取表头组件并将其放置在自己的位置。For example:例如:
container.setLayout(new BorderLayout()); container.add(table.getTableHeader(), BorderLayout.PAGE_START); container.add(table, BorderLayout.CENTER);
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.当表格变得更宽或更窄时(当用户调整包含表格的窗口的大小时可能会发生),所有列宽都会相应改变。
When the user resizes a column by dragging its right border, then either other columns must change size, or the table's size must change. 当用户通过拖动列的右边框来调整列的大小时,其他列必须更改大小,或者表的大小必须更改。By default, the table's size remains the same, and all columns to the right of the drag point resize to accommodate space added to or removed from the column to the left of the drag point.默认情况下,表的大小保持不变,拖动点右侧的所有列都会调整大小,以适应添加到拖动点左侧列或从拖动点左侧的列中删除的空间。
To customize initial column widths, you can invoke 要自定义初始列宽,可以对表的每一列调用setPreferredWidth
on each of your table's columns. setPreferredWidth
。This sets both the preferred widths of the columns and their approximate relative widths. 这将设置列的首选宽度及其近似相对宽度。For example, adding the following code to 例如,向SimpleTableDemo
makes its third column bigger than the other columns:SimpleTableDemo
添加以下代码会使其第三列大于其他列:
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); } }
As the preceding code shows, each column in a table is represented by a 如前面的代码所示,表中的每一列都由TableColumn
object. TableColumn
对象表示。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. 提供列的最小、首选和最大宽度的getter和setter方法,以及获取当前宽度的方法。For an example of setting cell widths based on an approximation of the space needed to draw the cells' contents, see the 有关根据绘制单元格内容所需空间的近似值设置单元格宽度的示例,请参阅initColumnSizes
method in TableRenderDemo.java
.TableRenderDemo.java
中的initColumnSizes
方法。
When the user explicitly resizes columns, the columns' preferred widths are set such that the user-specified sizes become the columns' new current widths. 当用户显式调整列的大小时,将设置列的首选宽度,以便用户指定的大小成为列的新当前宽度。However, when table itself is resized typically because the window has resized ; the columns' preferred widths do not change. 然而,当表本身被调整大小时;通常是因为窗口已调整大小;列的首选宽度不变。Instead, the existing preferred widths are used to calculate new column widths to fill the available space.相反,现有的首选宽度用于计算新列宽以填充可用空间。
You can change a table's resize behavior by invoking 您可以通过调用setAutoResizeMode
.setAutoResizeMode
来更改表的调整大小行为。
In its default configuration, a table supports a selection that consists of one or more rows. 在默认配置中,表支持由一行或多行组成的选择。The user can select a contiguous range of rows or an arbitrary set of rows. 用户可以选择连续范围的行或任意行集。The last cell that the user indicated gets a special indication; in the Metal look and feel, the cell is outlined. 用户指示的最后一个小区获得特殊指示;在金属外观和感觉中,细胞被勾勒出来。This cell is known as the lead selection; it is sometimes called "the cell with the focus" or "the current cell".该单元称为引线选择;它有时被称为“具有焦点的单元格”或“当前单元格”。
The user uses the mouse and/or keyboard to make selections, as described in the following table:用户使用鼠标和/或键盘进行选择,如下表所述:
To see how selections work, click the Launch button to run 要查看选择的工作方式,请单击启动按钮,使用Java™Web启动运行TableSelectionDemo
using Java™ Web Start (download JDK 7 or later). TableSelectionDemo
(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
This example program presents the familiar table, and allows the user to manipulate certain JTable options. 这个示例程序提供了熟悉的表,并允许用户操作某些JTable选项。There is also a text pane that logs selection events.还有一个记录选择事件的文本窗格。
In the screenshot below, a user has run the program, clicked in the first row, then control-clicked in the third row. 在下面的屏幕截图中,用户运行程序,单击第一行,然后单击第三行中的控件。Notice the outline around the last cell clicked; this is how the Metal look and feel highlights the lead selection.注意最后单击的单元格周围的轮廓;这是金属外观和感觉如何突出前导选区。
Under "Selection Mode" there are a set of radio buttons. 在“选择模式”下,有一组单选按钮。Click the one labelled "Single Selection". Now you can only select one row at a time. 单击标记为“单选”的选项。现在一次只能选择一行。If you click on the "Single Interval Selection" radio button, you can select a set of rows that must be contiguous.如果单击“单间隔选择”单选按钮,则可以选择一组必须连续的行。
All of the radio buttons under "Selection Mode" invoke “选择模式”下的所有单选按钮调用JTable.setSelectionMode
. JTable.setSelectionMode
。This method takes a single argument, which must be one of the following constants defined in 该方法采用一个参数,该参数必须是javax.swing.ListSelectionModel
: MULTIPLE_INTERVAL_SELECTION
, SINGLE_INTERVAL_SELECTION
, and SINGLE_SELECTION
.javax.swing.ListSelectionModel
中定义的以下常量之一:MULTIPLE_INTERVAL_SELECTION
、SINGLE_INTERVAL_SELECTION
和SINGLE_SELECTION
。
Returning to 返回TableSelectionDemo
, notice the three option check boxes under "Selection Options." TableSelectionDemo
,注意“选择选项”下的三个选项复选框。Each of check box controls the state of a 每个复选框控制boolean
bound variable defined by JTable
:JTable
定义的boolean
绑定变量的状态:
rowSelectionAllowed
which has setter method setRowSelectionAllowed
and getter method getRowSelectionAllowed
. rowSelectionAllowed
,它具有setter方法setRowSelectionAllowed
和getter方法getRowSelectionAllowed
。true
(and the columnSelectionAllowed
property is false
), the user can select by row.true
(columnSelectionAllowed
属性为false
)时,用户可以按行进行选择。columnSelectionAllowed
which has setter method setColumnSelectionAllowed
and getter method getColumnSelectionAllowed
. columnSelectionAllowed
,它具有setter方法setColumnSelectionAllowed
和getter方法getColumnSelectionAllowed
。true
(and the rowSelectionAllowed
bound property is false
), the user can select by column.true
(并且rowSelectionAllowed
绑定属性为false
)时,用户可以按列进行选择。cellSelectionEnabled
, which has setter method setCellSelectionEnabled
and getter method getCellSelectionEnabled
. cellSelectionEnabled
,它具有setter方法setCellSelectionEnabled
和getter方法getCellSelctionEnabled
。true
, the user can select a single cell or rectangular block of cells.true
时,用户可以选择单个单元格或矩形单元格块。JTable
If you clear all three check boxes (setting all three bound properties to 如果清除所有三个复选框(将所有三个绑定属性设置为false
), there is no selection; only the lead selection is shown.false
),则没有选择;仅显示导线选择。
You may notice that the "Cell Selection" check box is disabled in multiple interval selection mode. 您可能会注意到,“单元格选择”复选框在多间隔选择模式下被禁用。This is because cell selection is not supported in this mode in the demo. 这是因为演示中此模式不支持单元格选择。You can specify selection by cell in multiple interval selection mode, but the result is a table that does not produce useful selections.可以在多间隔选择模式下指定“按单元格选择”,但结果是表格无法生成有用的选择。
You may also notice that changing any of the three selection options can affect the others. 您可能还注意到,更改三个选择选项中的任何一个都会影响其他选项。This is because allowing both row selection and column selection is exactly the same as enabling cell selection. 这是因为允许行选择和列选择与启用单元格选择完全相同。JTable
automatically updates the three bound variables as necessary to keep them consistent.JTable
根据需要自动更新三个绑定变量,以保持它们的一致性。
cellSelectionEnabled
to a value has the side effect of also setting both rowSelectionEnabled
and columnSelectionEnabled
to that value. cellSelectionEnabled
设置为值的副作用是同时将rowSelectionEnabled
和columnSelectionEnabled
设置为该值。rowSelectionEnabled
and columnSelectionEnabled
to a value has the side effect of also setting cellSelectionEnabled
to that value. rowSelectionEnabled
和columnSelectionEnabled
设置为一个值会产生将cellSelectionEnabled
设置为该值的副作用。rowSelectionEnabled
and columnSelectionEnabled
to different values has the side effect of also setting cellSelectionEnabled
to false
. rowSelectionEnabled
和columnSelectionEnabled
设置为不同的值也会产生将cellSelectionEnabled
设置为false
的副作用。To retrieve the current selection, use 要检索当前选择,请使用JTable.getSelectedRows
which returns an array of row indexes, and JTable.getSelectedColumns
which returns an array of column indexes. JTable.getSelectedRows
返回行索引数组,使用JTable.getSelectedColumns
返回列索引数组。To retrieve the coordinates of the lead selection, refer to the selection models for the table itself and for the table's column model. 要检索潜在客户选择的坐标,请参考表本身和表列模型的选择模型。The following code formats a string containing the row and column of the lead selection:以下代码格式化包含潜在客户选择的行和列的字符串:
String.format("Lead Selection: %d, %d. ", table.getSelectionModel().getLeadSelectionIndex(), table.getColumnModel().getSelectionModel().getLeadSelectionIndex());
User selections generate a number of events. 用户选择会生成许多事件。For information on these, refer to How to Write a List Selection Listener in the Writing Event Listeners lesson.有关这些的信息,请参阅“编写事件侦听器”课程中的“如何编写列表选择侦听器”。
Every table object uses a table model object to manage the actual table data. 每个表对象都使用一个表模型对象来管理实际的表数据。A table model object must implement the 表模型对象必须实现TableModel
interface. TableModel
接口。If the programmer does not provide a table model object, 如果程序员没有提供表模型对象,JTable
automatically creates an instance of DefaultTableModel
. JTable
会自动创建DefaultTableModel
的实例。This relationship is illustrated below.这种关系如下所示。
The JTable
constructor used by SimpleTableDemo
creates its table model with code like this:SimpleTableDemo
使用的JTable
构造函数使用如下代码创建其表模型:
new AbstractTableModel() { public String getColumnName(int col) { return columnNames[col].toString(); } public int getRowCount() { return rowData.length; } public int getColumnCount() { return columnNames.length; } public Object getValueAt(int row, int col) { return rowData[row][col]; } public boolean isCellEditable(int row, int col) { return true; } public void setValueAt(Object value, int row, int col) { rowData[row][col] = value; fireTableCellUpdated(row, col); } }
As the preceding code shows, implementing a table model can be simple. 如前面的代码所示,实现表模型非常简单。Generally, you implement your table model in a subclass of the 通常,您在AbstractTableModel
class.AbstractTableModel
类的子类中实现表模型。
Your model might hold its data in an array, vector, or hash map, or it might get the data from an outside source such as a database. 您的模型可能将其数据保存在数组、向量或哈希映射中,也可能从外部源(如数据库)获取数据。It might even generate the data at execution time.它甚至可能在执行时生成数据。
This table is different from the 该表与SimpleTableDemo
table in the following ways:SimpleTableDemo
表的不同之处如下:
TableDemo
's custom table model, even though it is simple, can easily determine the data's type, helping the JTable
display the data in the best format. TableDemo
的自定义表模型虽然简单,但可以轻松确定数据的类型,帮助JTable
以最佳格式显示数据。SimpleTableDemo
's automatically created table model, on the other hand, does not know that the # of Years column contains numbers (which should generally be right aligned and have a particular format). SimpleTableDemo
自动创建的表模型不知道#of Years列包含数字(通常应右对齐并具有特定格式)。Vegetarian
column contains boolean values, which can be represented by check boxes.Vegetarian
列包含布尔值,可以用复选框表示。TableDemo
does not let you edit the name columns; it does, however, let you edit the other columns. TableDemo
中实现的自定义表模型不允许您编辑名称列;但是,它允许您编辑其他列。SimpleTableDemo
, all cells are editable.SimpleTableDemo
中,所有单元格都是可编辑的。See below the code taken from 下面是从TableDemo.java
that is different from the SimpleTableDemo.java
. SimpleTableDemo.java
中获取的代码,它不同于SimpleTableDemo.java
。Bold font indicates the code that makes this table's model different from the table model defined automatically for 粗体表示使此表的模型不同于为SimpleTableDemo
.SimpleTableDemo
自动定义的表模型的代码。
public TableDemo() { ... JTable table = new JTable(new MyTableModel()); ... } class MyTableModel extends AbstractTableModel { private String[] columnNames = ...//same as before... private Object[][] data = ...//same as before... public int getColumnCount() { return columnNames.length; } public int getRowCount() { return data.length; } public String getColumnName(int col) { return columnNames[col]; } public Object getValueAt(int row, int col) { return data[row][col]; } public Class getColumnClass(int c) { return getValueAt(0, c).getClass(); } /* * Don't need to implement this method unless your table's * editable. */ public boolean isCellEditable(int row, int col) { //Note that the data/cell address is constant, //no matter where the cell appears onscreen. if (col < 2) { return false; } else { return true; } } /* * Don't need to implement this method unless your table's * data can change. */ public void setValueAt(Object value, int row, int col) { data[row][col] = value; fireTableCellUpdated(row, col); } ... }
A table model can have a set of listeners that are notified whenever the table data changes. 表模型可以有一组监听器,每当表数据发生变化时都会通知监听器。Listeners are instances of 监听器是TableModelListener
. TableModelListener
的实例。In the following example code, 在下面的示例代码中,SimpleTableDemo
is extended to include such a listener. SimpleTableDemo
被扩展为包含这样一个监听器。New code is in bold.新代码以粗体显示。
import javax.swing.event.*; import javax.swing.table.TableModel; public class SimpleTableDemo ... implements TableModelListener{ ... public SimpleTableDemo() { ... table.getModel().addTableModelListener(this); ... } public void tableChanged(TableModelEvent e) { int row = e.getFirstRow(); int column = e.getColumn(); TableModel model = (TableModel)e.getSource(); String columnName = model.getColumnName(column); Object data = model.getValueAt(row, column); ...// Do something with the data... } ... }
In order to fire data change events the table model must know how to construct a 为了触发数据更改事件,表模型必须知道如何构造TableModelEvent
object. TableModelEvent
对象。This can be a complex procedure, but is already implemented in 这可能是一个复杂的过程,但已在DefaultTableModel
. DefaultTableModel
中实现。You can either allow 您可以允许JTable
to use its default instance of DefaultTableModel
, or create your own custom subclass of DefaultTableModel
.JTable
使用其默认的DefaultTableModel
实例,也可以创建自己的DefauctTableModel
自定义子类。
If 如果DefaultTableModel
is not a suitable base class for your custom table model class, consider subclassing AbstractTableModel
. DefaultTableModel
不是自定义表模型类的合适基类,请考虑将AbstractTableModel
子类化。This class implements a simple framework for constructing 此类实现了一个用于构造TableModelEvent
objects. TableModelEvent
对象的简单框架。Your custom class simply needs to invoke one the following 每次外部源更改表数据时,自定义类只需调用以下AbstractTableModel
methods each time table data is changed by an external source.AbstractTableModel
方法之一。
fireTableCellUpdated |
|
fireTableRowsUpdated |
|
fireTableDataChanged |
|
fireTableRowsInserted |
|
fireTableRowsDeleted |
|
fireTableStructureChanged |
Before you go on to the next few tasks, you need to understand how tables draw their cells. 在继续下几个任务之前,您需要了解表如何绘制单元格。You might expect each cell in a table to be a component. 您可能希望表中的每个单元格都是一个组件。However, for performance reasons, Swing tables are implemented differently.然而,出于性能原因,Swing表的实现方式不同。
Instead, a single cell renderer is generally used to draw all of the cells that contain the same type of data. 相反,通常使用单个单元格渲染器来绘制包含相同类型数据的所有单元格。You can think of the renderer as a configurable ink stamp that the table uses to stamp appropriately formatted data onto each cell. 您可以将渲染器视为一个可配置的墨迹标记,表使用它将适当格式化的数据标记到每个单元格上。When the user starts to edit a cell's data, a cell editor takes over the cell, controlling the cell's editing behavior.当用户开始编辑单元格数据时,单元格编辑器将接管单元格,控制单元格的编辑行为。
For example, each cell in the # of Years column in 例如,TableDemo
contains Number
data specifically, an Integer
object. TableDemo
中# of Years列中的每个单元格包含数字数据;特别是Integer
对象。By default, the cell renderer for a 默认情况下,包含Number
-containing column uses a single JLabel
instance to draw the appropriate numbers, right-aligned, on the column's cells. Number
的列的单元格渲染器使用单个JLabel
实例在列的单元格上绘制适当的数字(右对齐)。If the user begins editing one of the cells, the default cell editor uses a right-aligned 如果用户开始编辑其中一个单元格,默认单元格编辑器将使用右对齐的JTextField
to control the cell editing.JTextField
来控制单元格编辑。
To choose the renderer that displays the cells in a column, a table first determines whether you specified a renderer for that particular column. 要选择显示列中单元格的渲染器,表首先确定是否为该特定列指定了渲染器。If you did not, then the table invokes the table model's 如果没有,则表调用表模型的getColumnClass
method, which gets the data type of the column's cells. getColumnClass
方法,该方法获取列单元格的数据类型。Next, the table compares the column's data type with a list of data types for which cell renderers are registered. 接下来,该表将列的数据类型与单元格渲染器注册的数据类型列表进行比较。This list is initialized by the table, but you can add to it or change it. 此列表由表初始化,但您可以添加或更改它。Currently, tables put the following types of data in the list:目前,表中列出了以下类型的数据:
Boolean
Number
Double
, Float
Number
, but the object-to-text translation is performed by a NumberFormat
instance (using the default number format for the current locale).Number
相同,但对象到文本的转换由NumberFormat
实例执行(使用当前区域设置的默认数字格式)。Date
DateFormat
instance (using a short style for the date and time).DateFormat
实例执行对象到文本的转换(使用日期和时间的短样式)。ImageIcon
, Icon
Object
Cell editors are chosen using a similar algorithm.使用类似的算法选择单元格编辑器。
Remember that if you let a table create its own model, it uses 请记住,如果让一个表创建自己的模型,它将使用Object
as the type of every column. Object
作为每个列的类型。To specify more precise column types, the table model must define the 要指定更精确的列类型,表模型必须适当地定义getColumnClass
method appropriately, as demonstrated by TableDemo.java
.getColumnClass
方法,如TableDemo.java
所示。
Keep in mind that although renderers determine how each cell or column header looks and can specify its tool tip text, a renderer does not handle events. 请记住,尽管渲染器确定每个单元格或列标题的外观,并可以指定其工具提示文本,但渲染器不处理事件。If you need to pick up the events that take place inside a table, the technique you use varies by the sort of event you are interested in:如果您需要提取表中发生的事件,您使用的技术因您感兴趣的事件类型而异:
JTableHeader object. JTableHeader 对象上注册适当类型的鼠标侦听器。TableSorter.java for an example.)TableSorter.java 。) | |
JTable object.JTable 对象上注册适当的侦听器。 |
The next few sections tell you how to customize display and editing by specifying renderers and editors. 接下来的几节将告诉您如何通过指定渲染器和编辑器来自定义显示和编辑。You can specify cell renderers and editors either by column or by data type.可以按列或按数据类型指定单元格渲染器和编辑器。
This section tells you how to create and specify a cell renderer. 本节介绍如何创建和指定单元格渲染器。You can set a type-specific cell renderer using the 可以使用JTable
method setDefaultRenderer
. JTable
方法setDefaultRenderer
设置特定于类型的单元格渲染器。To specify that cells in a particular column should use a renderer, you use the 要指定特定列中的单元格应使用渲染器,请使用TableColumn
method setCellRenderer
. TableColumn
方法setCellRenderer
。You can even specify a cell-specific renderer by creating a 您甚至可以通过创建JTable
subclass.JTable
子类来指定特定于单元的渲染器。
It is easy to customize the text or image rendered by the default renderer, 自定义默认渲染器DefaultTableCellRenderer
. DefaultTableCellRenderer
渲染的文本或图像很容易。You just create a subclass and implement the 您只需创建一个子类并实现setValue
method so that it invokes setText
or setIcon
with the appropriate string or image. setValue
方法,以便它使用适当的字符串或图像调用setText
或setIcon
。For example, here is how the default date renderer is implemented:例如,以下是如何实现默认日期渲染器:
static class DateRenderer extends DefaultTableCellRenderer { DateFormat formatter; public DateRenderer() { super(); } public void setValue(Object value) { if (formatter==null) { formatter = DateFormat.getDateInstance(); } setText((value == null) ? "" : formatter.format(value)); } }
If extending 如果扩展DefaultTableCellRenderer
is insufficient, you can build a renderer using another superclass. DefaultTableCellRenderer
不够,可以使用另一个超类构建渲染器。The easiest way is to create a subclass of an existing component, making your subclass implement the 最简单的方法是创建现有组件的子类,使子类实现TableCellRenderer
interface. TableCellRenderer
接口。TableCellRenderer
requires just one method: getTableCellRendererComponent
. TableCellRenderer
只需要一个方法:getTableCellRendererComponent
。Your implementation of this method should set up the rendering component to reflect the passed-in state, and then return the component.此方法的实现应设置呈现组件以反映传入状态,然后返回组件。
In the snapshot of 在TableDialogEditDemo
, the renderer used for Favorite Color cells is a subclass of JLabel
called ColorRenderer
. TableDialogEditDemo
的快照中,用于常用颜色单元格的渲染器是JLabel
的一个子类,称为ColorRenderer
。Here are excerpts from 下面是ColorRenderer.java
that show how it is implemented.ColorRenderer.java
的摘录,展示了它是如何实现的。
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:TableDialogEditDemo.java
中的代码,它将ColorRenderer
实例注册为所有Color
数据的默认渲染器:
table.setDefaultRenderer(Color.class, new ColorRenderer(true));
To specify a cell-specific renderer, you need to define a 要指定特定于单元的渲染器,需要定义一个JTable
subclass that overrides the getCellRenderer
method. JTable
子类,该子类重写getCellRenderer
方法。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); } };
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. JTable
的getToolTipText(MouseEvent)
方法实现来指定工具提示文本可能更简单。This section shows you how to use both techniques.本节向您展示如何使用这两种技术。
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.JComponent
之后,调用其上的setToolTipText
方法。
An example of setting tool tips for cells is in 为单元格设置工具提示的示例在TableRenderDemo
. TableRenderDemo
中。Click the Launch button to run it using Java™ Web Start (download JDK 7 or later). 单击启动按钮,使用Java™Web启动运行它(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
The source code is in 源代码在TableRenderDemo.java
. TableRenderDemo.java
中。It adds tool tips to the cells of the Sport column with the following code:它使用以下代码向“运动”列的单元格添加工具提示:
//Set up tool tips for the sport cells. DefaultTableCellRenderer renderer = new DefaultTableCellRenderer(); renderer.setToolTipText("Click for combo box"); sportColumn.setCellRenderer(renderer);
Although the tool tip text in the previous example is static, you can also implement tool tips whose text changes depending on the state of the cell or program. 尽管上一示例中的工具提示文本是静态的,但您也可以实现工具提示,其文本根据单元格或程序的状态而变化。Here are a couple ways to do so:以下是几种方法:
getTableCellRendererComponent
method.getTableCellRenderComponent
方法添加一些代码。JTable
method getToolTipText(MouseEvent)
.JTable
方法gettooltipext(MouseEvent)
。An example of adding code to a cell renderer is in 将代码添加到单元格渲染器的示例在TableDialogEditDemo
. TableDialogEditDemo
中。Click the Launch button to run it using Java™ Web Start (download JDK 7 or later). 单击启动按钮,使用Java™Web启动运行它(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
TableDialogEditDemo
uses a renderer for colors, implemented in ColorRenderer.java
, that sets the tool tip text using the boldface code in the following snippet:TableDialogEditDemo
使用ColorRenderer.java
中实现的颜色渲染器,该渲染器使用以下代码段中的粗体代码设置工具提示文本:
public class ColorRenderer extends JLabel implements TableCellRenderer { ... public Component getTableCellRendererComponent( JTable table, Object color, boolean isSelected, boolean hasFocus, int row, int column) { Color newColor = (Color)color; ... setToolTipText("RGB value: " + newColor.getRed() + ", " + newColor.getGreen() + ", " + newColor.getBlue()); return this; } }
Here is an example of what the tool tip looks like:以下是工具提示的示例:
You can specify tool tip text by overriding 您可以通过重写JTable
's getToolTipText(MouseEvent)
method. JTable
的getToolTipText(MouseEvent)
方法来指定工具提示文本。The program 程序TableToolTipsDemo
shows how. Click the Launch button to run it using Java™ Web Start (download JDK 7 or later). TableToolTipsDemo
显示了怎样做。单击启动按钮,使用Java™Web启动运行它(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
The cells with tool tips are in the Sport and Vegetarian columns. Here is a picture of its tool tip:带有工具提示的单元格在运动和素食列中。以下是其工具提示的图片:
Here is the code from 以下是TableToolTipsDemo.java
that implements tool tips for cells in the Sport and Vegetarian columns:TableToolTipsDemo.java
中的代码,它为运动和素食专栏中的单元格实现了工具提示:
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; } ... }
The code is fairly straightforward, except perhaps for the call to 代码相当简单,除了调用convertColumnIndexToModel
. convertColumnIndexToModel
之外。That call is necessary because if the user moves the columns around, the view's index for the column will not match the model's index for the column. 该调用是必要的,因为如果用户移动列,则该列的视图索引将与该列的模型索引不匹配。For example, the user might drag the Vegetarian column (which the model considers to be at index 4) so it is displayed as the first column at view index 0. 例如,用户可以拖动Vegetarian列(模型认为该列位于索引4),以便将其显示为第一列在视图索引0处。Since 由于prepareRenderer
provides the view index, you need to translate the view index to a model index so you can be sure the intended column has been selected.prepareRenderer
提供了视图索引,因此需要将视图索引转换为模型索引,以便确保已选择所需的列。
You can add a tool tip to a column header by setting the tool tip text for the table's 通过为表的JTableHeader
. JTableHeader
设置工具提示文本,可以将工具提示添加到列标题。Often, different column headers require different tool tip text. 通常,不同的列标题需要不同的工具提示文本。You can change the text by overriding the table header's 您可以通过重写表头的getToolTipText
method. getToolTipText
方法来更改文本。Alternately, you can invoke 或者,您可以调用TableColumn.setHeaderRenderer
to provide a custom renderer for the header.TableColumn.setHeaderRenderer
为标头提供自定义渲染器。
An example of using the same tool tip text for all column headers is in 在TableSorterDemo.java
. TableSorterDemo.java
中,为所有列标题使用相同的工具提示文本。Here is how it sets the tool tip text:以下是如何设置工具提示文本:
table.getTableHeader().setToolTipText( "Click to sort; Shift-Click to sort in reverse order");
TableToolTipsDemo.java
has an example of implementing column header tool tips that vary by column. 具有实现列标题工具提示的示例,这些提示随列而异。If you run 如果使用Java™Web启动运行TableToolTipsDemo
(click the Launch button) using Java™ Web Start (download JDK 7 or later). TableToolTipsDemo
(单击启动按钮)(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
You will see the tool tips when you mouse over any column header except for the first two. 当您将鼠标移到除前两个之外的任何列标题上时,您将看到工具提示。No tool tips were supplied for the name columns since they seemed self-explanatory. 没有为名称列提供工具提示,因为它们似乎是自解释的。Here is a picture of one of the column header tool tips:以下是列标题工具提示之一的图片:
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. JTableHeader
的子类,该子类重写了getToolTipText(MouseEvent)
方法,以便返回当前列的文本。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.JTable
方法createDefaultTableHeader
,以便它返回JTableHeader
子类的实例。
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]; } }; } };
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
:autoCreateRowSorter
绑定属性设置为true
:
JTable table = new JTable(); table.setAutoCreateRowSorter(true);
This action defines a row sorter that is an instance of 此操作定义了一个行排序器,该行排序器是javax.swing.table.TableRowSorter
. 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 这在
, as seen in this screen shot:TableSortDemo.java
中演示,如本屏幕截图所示:TableSortDemo.java
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
的实例,并指定它是表的排序器对象。
TableRowSorter<TableModel> sorter = new TableRowSorter<TableModel>(table.getModel()); table.setRowSorter(sorter);
TableRowSorter
uses java.util.Comparator
objects to sort its rows. TableRowSorter
使用java.util.Comparator
对象对其行进行排序。A class that implements this interface must provide a method called 实现此接口的类必须提供一个名为compare
that defines how any two objects are compared for the purpose of sorting. compare
的方法,该方法定义如何比较任何两个对象以进行排序。For example, the following code creates a 例如,以下代码创建了一个Comparator
that sorts a set of strings by the last word in each string:Comparator
,该比较器按照每个字符串中的最后一个单词对一组字符串进行排序:
Comparator<String> comparator = new Comparator<String>() { public int compare(String s1, String s2) { String[] strings1 = s1.split("\\s"); String[] strings2 = s2.split("\\s"); return strings1[strings1.length - 1] .compareTo(strings2[strings2.length - 1]); } };
This example is fairly simplistic; more typically, a 这个例子相当简单;更典型的是,比较器实现是Comparator
implementation is a subclass of java.text.Collator
. java.text.Collator
的子类。You can define your own subclass, use the factory methods in 您可以定义自己的子类,使用Collator
to obtain a Comparator
for a specific locale, or use java.text.RuleBasedCollator
.Collator
中的工厂方法获得特定区域设置的Comparator
,或者使用java.text.RuleBasedCollator
。
To determine which 为了确定列要使用哪个Comparator
to use for a column, TableRowSorter
attempts to apply each of the following rules in turn. Comparator
,TableRowSorter
尝试依次应用以下规则。Rules are followed in the order listed below; the first rule that provides the sorter with a 按下列顺序遵守规则;使用为分拣机提供Comparator
is used, and the remaining rules ignored.Comparator
的第一条规则,忽略其余规则。
setComparator
, use that comparator.Comparator
指定了比较器,则使用该比较器。TableModel.getColumnClass
returns String.class
for that column), use a comparator that sorts the strings based on the current locale.TableModel.getColumnClass
返回该列的String.class
),则使用比较器根据当前区域设置对字符串进行排序。TableModel.getColumnClass
implements Comparable
, use a comparator that sorts the strings based on the values returned by Comparable.compareTo
.TableModel.getColumnClass
返回的列类实现了Comparable
,则使用比较器根据Comparable.compareTo
返回的值对字符串进行排序。setStringConverter
, use a comparator that sorts the resulting string representations based on the current locale.setStringConverter
为表指定了字符串转换器,请使用比较器,该比较器根据当前区域设置对结果字符串表示进行排序。toString
on the column data and sorts the resulting strings based on the current locale.toString
,并根据当前区域设置对结果字符串进行排序。For more sophisticated kinds of sorting, subclass 对于更复杂的排序,子类TableRowSorter
or its parent class javax.swing.DefaultRowSorter
.TableRowSorter
或其父类javax.swing.DefaultRowSorter
。
To specify the sort order and sort precedence for columns, invoke 要指定列的排序顺序和排序优先级,请调用setSortKeys
. setSortKeys
。Here is an example that sorts the table used in the examples by the first two columns. 下面的示例按前两列对示例中使用的表进行排序。The precedence of the columns in the sort is indicated by the order of the sort keys in the sort key list. 排序中列的优先级由排序键列表中排序键的顺序指示。In this case, the second column has the first sort key, so they rows are sorted by first name, then last name.在本例中,第二列具有第一个排序键,因此这些行按名字排序,然后按姓氏排序。
List <RowSorter.SortKey> sortKeys = new ArrayList<RowSorter.SortKey>(); sortKeys.add(new RowSorter.SortKey(1, SortOrder.ASCENDING)); sortKeys.add(new RowSorter.SortKey(0, SortOrder.ASCENDING)); sorter.setSortKeys(sortKeys);
In addition to reordering the results, a table sorter can also specify which rows will be displayed. 除了对结果重新排序之外,表排序器还可以指定将显示哪些行。This is known as filtering. 这被称为筛选。TableRowSorter
implements filtering using javax.swing.RowFilter
objects. TableRowSorter
使用javax.swing.RowFilter
对象实现筛选。RowFilter
implements several factory methods that create common kinds of filters. 实现多个工厂方法,用于创建常见类型的筛选器。For example, 例如,regexFilter
returns a RowFilter
that filters based on a regular expression.regexFilter
返回基于正则表达式进行筛选的RowFilter
。
In the following example code, you explicitly create a sorter object so you can later use it to specify a filter:在下面的示例代码中,您显式创建了一个排序器对象,以便以后可以使用它指定筛选器:
MyTableModel model = new MyTableModel(); sorter = new TableRowSorter<MyTableModel>(model); table = new JTable(model); table.setRowSorter(sorter);
Then you filter based on the current value of a text field:然后根据文本字段的当前值进行筛选:
private void newFilter() { RowFilter<MyTableModel, Object> rf = null; //If current expression doesn't parse, don't update. try { rf = RowFilter.regexFilter(filterText.getText(), 0); } catch (java.util.regex.PatternSyntaxException e) { return; } sorter.setRowFilter(rf); }
In a subsequent example, 在随后的示例中,每次文本字段更改时都会调用newFilter()
is invoked every time the text field changes. newFilter()
。When the user enters complicated regular expressions, the 当用户输入复杂的正则表达式时,try...catch
prevents the syntax exception from interfering with input.try...catch
可以防止语法异常干扰输入。
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
.JTable
提供了从模型坐标转换为视图坐标的方法;convertColumnIndexToView
和convertRowIndexToView
;并将视图坐标转换为模型坐标;convertColumnIndexToModel
和convertRowIndexToModel
。
The following example brings together the ideas discussed in this section. 下面的示例将本节中讨论的想法结合在一起。TableFilterDemo.java
adds a small number of changes to 向TableDemo
. TableDemo
添加少量更改。These include the code snippets earlier in this section, which provide a sorter for the main table, and use a text field to supply the filtering regular expression. 其中包括本节前面的代码片段,它为主表提供了一个排序器,并使用文本字段提供筛选正则表达式。The following screen shot shows 以下屏幕截图显示了完成任何排序或筛选之前的TableFilterDemo
before any sorting or filtering has been done. TableFilterDemo
。Notice that row 3 in the model is still the same as row 3 in the view:请注意,模型中的第3行仍然与视图中的第三行相同:
If the user clicks twice on the second column, the fourth row becomes the first row but only in the view:如果用户在第二列上单击两次,则第四行变为第一行;但仅在以下视图中:
As previously noted, the text the user enters in the "Filter Text" text field defines a filter that determines which rows are shown. 如前所述,用户在“筛选器文本”文本字段中输入的文本定义了一个筛选器,用于确定显示哪些行。As with sorting, filtering can cause view coordinates to diverge from model coordinates:与排序一样,筛选可能导致视图坐标偏离模型坐标:
Here is the code that updates the status field to reflect the current selection:下面是更新状态字段以反映当前选择的代码:
table.getSelectionModel().addListSelectionListener( new ListSelectionListener() { public void valueChanged(ListSelectionEvent event) { int viewRow = table.getSelectedRow(); if (viewRow < 0) { //Selection got filtered away. statusText.setText(""); } else { int modelRow = table.convertRowIndexToModel(viewRow); statusText.setText( String.format("Selected Row in view: %d. " + "Selected Row in model: %d.", viewRow, modelRow)); } } } );
Setting up a combo box as an editor is simple, as the following example shows. 将组合框设置为编辑器很简单,如下例所示。The bold line of code sets up the combo box as the editor for a specific column.粗体代码行将组合框设置为特定列的编辑器。
TableColumn sportColumn = table.getColumnModel().getColumn(2); ... JComboBox comboBox = new JComboBox(); comboBox.addItem("Snowboarding"); comboBox.addItem("Rowing"); comboBox.addItem("Chasing toddlers"); comboBox.addItem("Speed reading"); comboBox.addItem("Teaching high school"); comboBox.addItem("None"); sportColumn.setCellEditor(new DefaultCellEditor(comboBox));
Here is a picture of the combo box editor in use:下面是正在使用的组合框编辑器的图片:
The preceding code is from 前面的代码来自TableRenderDemo.java
. TableRenderDemo.java
。You can run 您可以使用Java™Web启动运行TableRenderDemo(单击启动按钮)(下载JDK 7或更高版本)。TableRenderDemo
(click the Launch button) using Java™ Web Start (download JDK 7 or later). Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
Whether you are setting the editor for a single column of cells (using the 无论是为单列单元格(使用TableColumn
setCellEditor
method) or for a specific type of data (using the JTable
setDefaultEditor
method), you specify the editor using an argument that adheres to the TableCellEditor
interface. TableColumn
setCellEditor
方法)还是为特定类型的数据(使用JTable
setDefaultEditor方法
)设置编辑器,都可以使用符合TableCellEditor
接口的参数指定编辑器。Fortunately, the 幸运的是,DefaultCellEditor
class implements this interface and provides constructors to let you specify an editing component that is a JTextField
, JCheckBox
, or JComboBox
. DefaultCellEditor
类实现了这个接口,并提供了构造函数,让您可以指定一个编辑组件,即JTextField
、JCheckBox
或JComboBox
。Usually you do not have to explicitly specify a check box as an editor, since columns with 通常,您不必显式指定复选框作为编辑器,因为具有Boolean
data automatically use a check box renderer and editor.Boolean
数据的列会自动使用复选框渲染器和编辑器。
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. DefaultCellEditor
不支持其他类型的组件,您必须做更多的工作。You need to create a class that implements the 您需要创建一个实现TableCellEditor
interface. TableCellEditor
接口的类。The AbstractCellEditor
class is a good superclass to use. AbstractCellEditor
类是一个很好的超类。It implements 它实现了TableCellEditor
's superinterface, CellEditor
, saving you the trouble of implementing the event firing code necessary for cell editors.TableCellEditor
的超级界面CellEditor
,从而省去了实现单元格编辑器所需的事件触发代码的麻烦。
Your cell editor class needs to define at least two methods 单元格编辑器类需要定义至少两个方法;getCellEditorValue
and getTableCellEditorComponent
. getCellEditorValue
和getTableCellEditorComponent
。The getCellEditorValue
method, required by CellEditor
, returns the cell's current value. CellEditor
所需的getCellEditorValue
方法返回单元格的当前值。The getTableCellEditorComponent
method, required by TableCellEditor
, should configure and return the component that you want to use as the editor.TableCellEditor
所需的getTableCellEditorComponent
方法应配置并返回您要用作编辑器的组件。
Here is a picture of a table with a dialog that serves, indirectly, as a cell editor. 下面是一张带有对话框的表格的图片,该对话框间接用作单元格编辑器。When the user begins editing a cell in the Favorite Color column, a button (the true cell editor) appears and brings up the dialog, with which the user can choose a different color.当用户开始编辑“最喜爱的颜色”列中的单元格时,会出现一个按钮(真正的单元格编辑器),并打开对话框,用户可以使用该对话框选择不同的颜色。
You can run 您可以使用Java™Web启动运行TableDialogEditDemo
(click the Launch button) using Java™ Web Start (download JDK 7 or later). TableDialogEditDemo
(单击启动按钮)(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
Here is the code, taken from 下面是从ColorEditor.java
, that implements the cell editor.ColorEditor.java
中获取的代码,它实现了单元格编辑器。
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. fireEditingStopped
。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.fireEditingStopped
的调用让表知道它可以停用编辑器,让单元格再次由渲染器处理。
If a cell's default editor allows text entry, you get some error checking for free if the cell's type is specified as something other than 如果单元格的默认编辑器允许文本输入,则如果单元格的类型指定为String
or Object
. String
或Object
以外的其他类型,则可以免费进行一些错误检查。The error checking is a side effect of converting the entered text into an object of the proper type.错误检查是将输入的文本转换为正确类型的对象的副作用。
The automatic checking of user-entered strings occurs when the default editor attempts to create a new instance of the class associated with the cell's column. 当默认编辑器尝试创建与单元格列关联的类的新实例时,会自动检查用户输入的字符串。The default editor creates this instance using a constructor that takes a 默认编辑器使用以String
as an argument. String
作为参数的构造函数创建此实例。For example, in a column whose cells have type 例如,在单元格类型为Integer
, when the user types in "123" the default editor creates the corresponding Integer
using code equivalent to new Integer("123")
. Integer
的列中,当用户键入“123”时,默认编辑器使用与new Integer("123")
等效的代码创建相应的整数。If the constructor throws an exception, the cell's outline turns red and refuses to let focus move out of the cell. 如果构造函数抛出异常,单元格的轮廓将变为红色,并拒绝将焦点移出单元格。If you implement a class used as a column data type, you can use the default editor if your class supplies a constructor that takes a single argument of type 如果实现用作列数据类型的类,则可以使用默认编辑器,前提是类提供了一个采用String
.String
类型的单个参数的构造函数。
If you like having a text field as the editor for a cell, but want to customize it perhaps to check user-entered text more strictly or to react differently when the text is invalid you can change the cell editor to use a formatted text field. 如果您喜欢将文本字段用作单元格的编辑器,但希望自定义它也许是为了更严格地检查用户输入的文本,或者在文本无效时做出不同的反应;可以将单元格编辑器更改为使用格式化文本字段。The formatted text field can check the value either continuously while the user is typing or after the user has indicated the end of typing (such as by pressing Enter).格式化文本字段可以在用户键入时或在用户指示键入结束后(如按Enter键)连续检查值。
The following code, taken from a demo named 以下代码取自名为TableFTFEditDemo.java
, sets up a formatted text field as an editor that limits all integer values to be between 0 and 100. TableFTFEditDemo.java
的演示,将格式化文本字段设置为编辑器,将所有整数值限制在0和100之间。You can run 您可以使用Java™Web启动运行TableFTFEditDemo
(click the Launch button) using Java™ Web Start (download JDK 7 or later). TableFTFEditDemo
(单击启动按钮)(下载JDK 7或更高版本)。Or, to compile and run the example yourself, consult the example index.或者,要自己编译和运行示例,请参考示例索引。
The following code makes the formatted text field the editor for all columns that contain data of type 以下代码使格式化文本字段成为包含Integer
.Integer
类型数据的所有列的编辑器。
table.setDefaultEditor(Integer.class, new IntegerEditor(0, 100));
The IntegerEditor
class is implemented as a subclass of DefaultCellEditor
that uses a JFormattedTextField
instead of the JTextField
that DefaultCellEditor
supports. IntegerEditor
类实现为DefaultCellEditor
的子类,它使用JFormattedTextField
而不是DefaultCellEditor
支持的JTextField
。It accomplishes this by first setting up a formatted text field to use an integer format and have the specified minimum and maximum values, using the API described in How to Use Formatted Text Fields. 为此,它首先使用如何使用格式化文本字段中描述的API设置格式化文本字段以使用整数格式并具有指定的最小值和最大值。It then overrides the 然后,它覆盖了DefaultCellEditor
implementation of the getTableCellEditorComponent
, getCellEditorValue
, and stopCellEditing
methods, adding the operations that are necessary for formatted text fields.getTableCellEditorComponent
、getCellEditorValue
和stopCellEditing
方法的DefaultCellEditor
实现,添加了格式化文本字段所需的操作。
The override of getTableCellEditorComponent
sets the formatted text field's value property (and not just the text property it inherits from JTextField
) before the editor is shown. getTableCellEditorComponent
的重写在显示编辑器之前设置格式化文本字段的值属性(而不仅仅是它从JTextField
继承的文本属性)。The override of getCellEditorValue
keeps the cell value as an Integer
, rather than, say, the Long
value that the formatted text field's parser tends to return. getCellEditorValue
的覆盖将单元格值保持为Integer
,而不是格式化文本字段的解析器倾向于返回的Long
值。Finally, overriding 最后,重写stopCellEditing
lets you check whether the text is valid, possibly stopping the editor from being dismissed. stopCellEditing
可以检查文本是否有效,可能会阻止编辑器被关闭。If the text isn't valid, your implementation of 如果文本无效,则stopCellEditing
puts up a dialog that gives the user the option of continuing to edit or reverting to the last good value. stopCellEditing
的实现将弹出一个对话框,用户可以选择继续编辑或恢复到上一个有效值。The source code is a bit too long to include here, but you can find it in 源代码太长,无法包含在这里,但您可以在IntegerEditor.java
.IntegerEditor.java
中找到它。
JTable
provides a simple API for printing tables. 提供用于打印表格的简单API。The easiest way to print out a table is to invoke 打印表的最简单方法是调用JTable.print
with no arguments:JTable.print
而不带参数:
try { if (! table.print()) { System.err.println("User cancelled printing"); } } catch (java.awt.print.PrinterException e) { System.err.format("Cannot print %s%n", e.getMessage()); }
Invoking 在普通Swing应用程序上调用打印将打开标准print
on a normal Swing application brings up a standard printing dialog box. print
对话框。(On a headless application, the table is simply printed.) (在无头应用程序中,只需打印表格。)The return value indicates whether the user went ahead with the print job or cancelled it. 返回值指示用户是继续打印作业还是取消打印作业。JTable.print
can throw 可以抛出java.awt.print.PrinterException
, which is a checked exception; that's why the above example uses a try ... catch
.java.awt.print.PrinterException
,这是一个已检查的异常;这就是为什么上面的示例使用try ... catch
。
JTable
provides several overloads of 提供多个带有各种选项的print
with various options. print
重载。The following code from
shows how to define a page header:TablePrintDemo.java
中的以下代码显示了如何定义页眉:TablePrintDemo.java
MessageFormat header = new MessageFormat("Page {0,number,integer}"); try { table.print(JTable.PrintMode.FIT_WIDTH, header, null); } catch (java.awt.print.PrinterException e) { System.err.format("Cannot print %s%n", e.getMessage()); }
For more sophisticated printing applications, use 对于更复杂的打印应用程序,请使用JTable.getPrintable
to obtain a Printable
object for the table. JTable.getPrintable
获取表的可打印对象。For more on 有关Printable
, refer to the Printing lesson in the 2D Graphics trail.Printable
的更多信息,请参阅2D图形轨迹中的打印课程。
This table lists examples that use 下表列出了使用JTable
and where those examples are described.JTable
的示例以及这些示例的描述位置。
SimpleTableDemo
|
||
SimpleTable- |
SimpleTableDemo . SimpleTableDemo 。ALLOW_COLUMN_SELECTION and ALLOW_ROW_SELECTION constants, you can experiment with alternatives to the table default of allowing only rows to be selected.ALLOW_COLUMN_SELECTION 和ALLOW_ROW_SELECTION 常量,您可以尝试使用表默认值(仅允许选择行)的替代方案。 | |
TableDemo |
||
TableFTFEditDemo |
TableDemo to use a custom editor (a formatted text field variant) for all Integer data.TableDemo 以对所有Integer 数据使用自定义编辑器(格式化文本字段变量)。 | |
TableRenderDemo |
TableDemo to use a custom editor (a combo box) for all data in the Sport column. TableDemo 以使用自定义编辑器(组合框)来处理“运动”列中的所有数据。 | |
TableDialogEditDemo |
TableDemo to have a cell renderer and editor that display a color and let you choose a new one, using a color chooser dialog.TableDemo ,使其具有显示颜色的单元格渲染器和编辑器,并允许您使用颜色选择器对话框选择新颜色。 | |
TableToolTipsDemo |
||
TableSortDemo |
||
TableFilterDemo |
||
TablePrintDemo |
||
ListSelectionDemo |
||
SharedModelDemo |
ListSelectionDemo making the data model be shared between the table and list. ListSelectionDemo 上,使数据模型在表和列表之间共享。 |