JTabel 是表格组件,可以把数据以二维表格的形式显示出来,并且支持用户对表格中的数据进行编辑。表格组件是最复杂的组件之一,它的表格模型功能非常强大、灵活而易于执行。
JTable 类实现表格,常用构造方法如下:
- JTable():构造一个默认的 JTable,使用默认的数据模型、默认的列模型和默认的选择模型对其进行初始化。
- JTable(int numRows,int numColumns):使用 DefaultTableModel 构造具有 numRows 行和 numColumns 列个空单元格的 JTable。
- JTable(Object[][] rowData,Object[] columnNames):构造一个 JTable 来显示二 维数组 rowData 中的值,其列名称为 columnNames。
JTable 类的常用方法如下:
Swing 的表格功能强大,相关的接口、类较为丰富,本节只介绍 TableModel、TableCellRender、TableCellEditor 三个子类常用的方法。
- TableModel :定义了若干的方法:包括了存取表格字段(cell)的内容、计算表格的列数等等的基本存取操作,让设计者可以简单地利用TableModel来实作他所想要的表格。
- TableCellRender :表格单元格渲染器。
- TableCellEditor :表格编辑器,使表格中的数据处于可编辑状态。
TableModel常用方法如下:
方法名及返回值类型 | 说明 |
---|---|
getColumnCount() | 返回列模型中的列数 |
getColumnN ame(int column) | 返回出现在视图中 column 列位置处的列名称 |
getRowCount() | 返回 JTable 中可以显示的行数(给定无限空间) |
getRowSorter() | 返回负责排序的对象 |
getSelectedColumn() | 返回第一个选定列的索引,如果没有选定的列, 则返回 -1 |
getSelectedRow() | 返回第一个选定行的索引,如果没有选定的行, 则返回 -1 |
getValueAt(int row,int column) | 返回 row 和 column 位置的单元格值 |
isEditing() | 如果正在编辑单元格,则返回 true |
selectAll() | 选择表中的所有行、列和单元格 |
setColumnSelectionInterval(int index0,int index1) | 选择从 index0 到 |
index1之间(包含两端)的列
setRowSelectionInterval(int index0,int index1) | 选择从 index0 到 index1
之间(包含两端)的行
setTableHeader(JTableHeader tableHeader) | 将此 JTable 所使用的 tableHeader 设置为
newHeader
setUpdateSelectionOnSort(boolean update) | 指定排序后是否应该更新选择
setValueAt(Object a Value,int row,int column) | 设置表模型中 row 和 column 位置的单元格值
TableCellRender常用方法如下:
方法名及返回值类型 | 说明 |
---|---|
getTableCellRendererComponent() | 返回绘制在单元格上的控件 |
TableCellEditor常用方法如下:
方法名及返回值类型 | 说明 |
---|---|
getTableCellEditorComponent | 获取单元格的编辑器,可以自定义返回值 |
getCellEditorValue |
编辑结束之后,Table会从这个接口获取编辑之后的值,然后通过TableModel.setValue接口设置给table
示例
继承 MyFrame 类,使用 JTable 类创建一个包含 6 列的学生成绩表,并向表格中填充几行学生信息,修改第2列单元格渲染风格,并且除表头外,表格内容支持编辑。具体实现代码如下:
package com.supermap.desktop.samplecode.swing.table;
import com.supermap.desktop.samplecode.MyFrame;
import javax.swing.*;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import java.awt.*;
import java.util.ArrayList;
public class MyJTable extends MyFrame {
private MyJTable() {
JTable jTable = new JTable();
ArrayList<Data> data = new ArrayList<>();
data.add(new Data(0, "学生1", 20, 30, 40));
data.add(new Data(1, "学生2", 90, 92, 94));
data.add(new Data(2, "学生3", 80, 30, 20));
data.add(new Data(3, "学生4", 90, 99, 30));
jTable.setModel(new MyTableModel(data));
// 这里我们只修改第2列的渲染器,让他返回我们自定义的效果
jTable.getColumnModel().getColumn(1).setCellRenderer(new DefaultTableCellRenderer() {
public Component getTableCellRendererComponent(JTable table, Object value, boolean isSelected, boolean hasFocus, int row, int column) {
JLabel tableCellRendererComponent = (JLabel) super.getTableCellRendererComponent(table, value, isSelected, hasFocus, row, column);
tableCellRendererComponent.setText(((String) value));
tableCellRendererComponent.setBackground(row % 2 == 0 ? Color.WHITE : Color.CYAN);//设置交替的背景色
return tableCellRendererComponent;
}
});
// 修改第0列的编辑器为自定义的编辑器,实现:
// 0或其他 -> textField
// 1 -> checkBox
// 2 -> comboBox
//
jTable.getColumnModel().getColumn(0).setCellEditor(new DefaultCellEditor(new JComboBox()) {
JTextField textField = new JTextField();
JCheckBox checkBox = new JCheckBox();
JComboBox<String> comboBox = new JComboBox<>(new String[]{"0", "1", "2"});
JComponent currentComponent = null;
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
int intValue = (int) value;
switch (intValue) {
case 1:
currentComponent = checkBox;
checkBox.setSelected(true);
return checkBox;
case 2:
currentComponent = comboBox;
comboBox.setSelectedItem("2");
return comboBox;
default:
currentComponent = textField;
textField.setText(String.valueOf(value));
return textField;
}
}
public Object getCellEditorValue() {
if (currentComponent == checkBox) {
return checkBox.isSelected() ? 1 : 0;
} else if (currentComponent == comboBox) {
return Integer.valueOf(((String) comboBox.getSelectedItem()));
} else if (currentComponent == textField) {
return Integer.valueOf(textField.getText());
}
return super.getCellEditorValue();
}
});
this.add(new JScrollPane(jTable));
}
class MyTableModel extends DefaultTableModel {
private String[] columnNames = new String[]{
"id", "姓名", "语文", "数学", "英语", "总分"
};
private ArrayList<Data> data;
public MyTableModel(ArrayList<Data> data) {
this.data = data;
}
public Object getValueAt(int row, int column) {
// 根据行列号获取值
Data data = this.data.get(row);
switch (column) {
case 0:
return data.id;
case 1:
return data.name;
case 2:
return data.scoreA;
case 3:
return data.scoreB;
case 4:
return data.scoreC;
case 5:
return data.getTotal();// 修改单科成绩后,自动刷新总分
}
return super.getValueAt(row, column);
}
public void setValueAt(Object aValue, int row, int column) {
// 修改表格的值,cellEditor返回的值会进入这个方法设置
Data data = this.data.get(row);
switch (column) {
case 0:
data.id = (int) aValue;
break;
case 1:
data.name = (String) aValue;
break;
case 2:
data.scoreA = (int) aValue;
break;
case 3:
data.scoreB = (int) aValue;
break;
case 4:
data.scoreC = (int) aValue;
break;
}
}
public boolean isCellEditable(int row, int column) {
// 判断列是否可编辑,设置最后一列不可编辑
return column != columnNames.length - 1;
}
public String getColumnName(int column) {
// 获得每一列的列头
return columnNames[column];
}
public int getColumnCount() {
// 获取表格共有多少列
return columnNames.length;
}
public int getRowCount() {
// 获取表格共有多少行
return data != null ? data.size() : 0;
}
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 1) {
return String.class;
}
return Integer.class;
}
}
class Data {
int id;
String name;
int scoreA;
int scoreB;
int scoreC;
public Data(int id, String name, int scoreA, int scoreB, int scoreC) {
this.id = id;
this.name = name;
this.scoreA = scoreA;
this.scoreB = scoreB;
this.scoreC = scoreC;
}
public int getTotal() {
return scoreA + scoreB + scoreC;
}
}
public static void main(String[] args) {
MyJTable frame = new MyJTable();
frame.setVisible(true);
}
}
示例代码运行结果如下,表格中的内容都可编辑: