注:本文为学习笔记,原文为How to Use Tables,本文所有素材与代码均源于原文,可能会有部分更改。

JTable是Swing中的表格控件,它的外观如下所示:

没错,excel或者access数据库的编辑区就是JTable这样的控件了。

创建JTable

JTable提供了2个构造器可以让你用数据和头部直接生成它:

JTable(Object[][] rowData, Object[] columnNames)
JTable(Vector rowData, Vector columnNames)

这两个构造器有一些特性你必须要注意:

1.JTable所有的单元格都是可编辑的;

2.它将所有数据都当做string来处理。本来,JTable可以将布尔型数据用一个checkBox来进行展示,就像表1那样,在这里就不行了。

3.它要求你把所有数据都放到数组或vector中。如果你的数据来自于数据库,那么专门再填充到数组实在是多此一举。

呐,如果你不能忍受以上限制,那么就使用table Model来管理你的数据吧!

创建TableModel

如果程序没有显式地指定tableModel,JTable会自动生成一个 DefaultTableModel实例,这样做的副作用在上面已经说过了。我们自己创建tableModel可以让数据得到更好的展示,这样做的方法是继承AbstractTableModel。它已经提供了tableModel接口的大部分默认实现,在最低限度下,你只需要实现以下三个方法:

public int getRowCount();

public int getColumnCount();

public Object getValueAt(int row, int column);

当然,如果你的应用程序有其他定制化的功能,你可以自己实现AbstractTableModel的其它方法,比如:

public Class getColumnClass(int c)//JTable uses this method to determine the default renderer editor for each cell

public boolean isCellEditable(int row, int col)//Don't need to implement this method unless your table's editable

public void setValueAt(Object value, int row, int col) //Don't need to implement this method unless your table's data can change.

TableDemo.java示意了如何自己创建并使用tableModel。

将表格添加到容器中

一般情况下我们都是将JTable放到JScrollPane中,从而使用它的滚动功能。JScrollPane会很贴心地把表头放在表格上方,并在向下滑动时始终保持它可见。如果你就是不要用JScrollPane,那么记得在容器中添加表头哦~就像下面这样

container.setLayout(new BorderLayout());
container.add(table.getTableHeader(), BorderLayout.PAGE_START);
container.add(table, BorderLayout.CENTER);

设置和更改列宽

设置列宽,直接上代码:

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);
}
}

当你手动调整列宽时,其它列的宽度也会自动调整,因为窗体尺寸没变。

用户选择

与JList一样,JTable也支持三种选择模式:

  • 单独选择:SINGLE_SELECTION
  • 单重连续选择:SINGLE_INTERVAL_SELECTION
  • 多重连续选择:MULTIPLE_INTERVAL_SELECTION

具体来说,你还可以设置是否允许选择行、选择列或选择单元格。需要注意的是,行、列选择与单元格选择会相互影响的。

1.在MULTIPLE_INTERVAL_SELECTION模式下:

选择单元格被永远禁止;选择行、选择列相互排斥,要么选择若干行,要么选择若干列;

2.在SINGLE_INTERVAL_SELECTION模式下:

禁止选择单元格时,选择行、选择列相互排斥,要么选择连续行,要么选择连续列。

启用选择单元格时,三者必须同时被选中,此时单元格可被单独或连续选中。

3.在SINGLE_SELECTION模式下:

禁止选择单元格时,选择行、选择列相互排斥,要么选择一行,要么选择一列。

启用选择单元格时,三者必须同时被选中,每次只能选择一个单元格。

注意,在JTable中无法同时选择独立的多个单元格,因为其Selection模型非常简单,就是取行与列的交集。

对于已选择的行、列的提取,使用JTable.getSelectedRowsJTable.getSelectedRows来提取它们的index。而lead selection的提取则有点违反直觉,代码如下:

String.format("Lead Selection: %d, %d. ",
table.getSelectionModel().getLeadSelectionIndex(),
table.getColumnModel().getSelectionModel().getLeadSelectionIndex());

监听数据变更

为了监听数据的变更,你需要调用model的addTableModelListener方法来添加一个监听器,而这个监听器必须实现了TableModelListener接口。该接口只有一个void tableChanged(TableModelEvent e)方法,你需要在里面进行响应。TableModelEvent将提供必要的信息,来指示发生变更的位置。它的方法有:

int getColumn()//Returns the column for the event.

int getFirstRow()//Returns the first row that changed.

int getLastRow()//Returns the last row that changed.

int getType()//Returns the type of event - one of: INSERT, UPDATE and DELETE.

得到位置后,你就可以调用model的getValueAt方法来获取最新值。

触发数据变更事件

为了触发数据变更事件,model必须知道如何创建数据变更事件。虽然这个过程很复杂,但是DefaultTableModel已经实现了。所以,你要么使用JTable默认的DefaultTableModel,要么自己继承DefaultTableModel。呐,如果你认为DefaultTableModel不合适而自己继承了 AbstractTableModel,那么你就得自己动动手啦!当数据被外部源改变时,你需要激活以下方法:

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.

渲染器与编辑器

渲染器决定了单元格内容的展现形式,而编辑器决定单元格内容被编辑的方式。比如,默认情况下,数字使用右对齐的JLabel来展示,布尔型变量使用单选控件来展示;而你在编辑某些列时,可能希望从下拉菜单中选择内容,这就是编辑器的作用了。出于性能上的考虑,JTable并没有为每一个单元格提供独立的渲染器,而是根据数据类型来渲染的。JTable首先会检查该列是否指定了渲染器,没有的话就检查该列的数据类型,并查看对应的渲染器。而基础类型以外的对象基本都是调用其toString方法,并通过JLable来渲染的。编辑器也是一样。

当然,我们可以对渲染器进行定制,来满足特定的需求。对指定的列或指定的数据类型应用定制渲染器都可以。如果是前者你需要调用JTable的setDefaultRenderer方法;如果是后者你需要调用指定列的setCellRenderer方法。如果你要为特定的单元格指定渲染器,那你需要调用继承JTable并重载getCellRenderer 方法。构造渲染器的最简单方法是继承DefaultTableCellRenderer类,然后实现它的setValue方法,你在里面使用setText或者setIcon来定制你渲染的内容。如果这还不够,那你可以继承一个已经存在的组件并实现 TableCellRenderer接口,比如让你的JLable继承这个接口,然后将它作为渲染器使用。

Table Render Demo Project是一个定制渲染器与编辑器的绝好例子,运行效果如下:

单元格提示(Tool tips for Cells)

单元格提示效果如上图,鼠标悬停时可显示出定制内容。在默认情况下,它是由单元格的渲染器决定的;然而,你也可以重载JTable的getToolTipText(MouseEvent)实现。下面分别介绍这两种方法。

(1)为单元格渲染器添加提示,首先需要建立一个渲染器,确认它是一个JComponent,然后用它调用setToolTipText即可。以下代码来自于TableRenderDemo.java

//Set up tool tips for the sport cells.
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
sportColumn.setCellRenderer(renderer);

以下代码来自于 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;
}
}

(2)重载JTable的getToolTipText(MouseEvent)

在该方法中,找到指定列,然后返回指定的字符串。以下代码来自于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;
}
...
}

运行效果如下图:

表头提示

通常表头中的不同列都具有不同的文字提示。你可以通过重载表头的getToolTipText方法来改变文字提示,也可以调用TableColumn.setHeaderRenderer来为表头提供一个定制的渲染器。

以下代码来自于TableSorterDemo.java,它为所有列头提供了相同的文字提示:

table.getTableHeader().setToolTipText(
"Click to sort; Shift-Click to sort in reverse order");

以下代码来自于TableSorterDemo.java,它为后3列的列头提供不同的文字提示。

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];
}
};
}
};

运行效果如下:

排序和过滤

Swing-JTable用法-入门的更多相关文章

  1. JTable用法-实例

    前几篇文章介绍了JTable的基本用法,本文实现一个简单的JTable,算是前文的一个总结,并造福供拷贝党们. Swing-JTable用法-入门 Swing-JTable的渲染器与编辑器使用demo ...

  2. swing JTable

    JTable 实例 import java.awt.Dimension; import java.awt.GridBagConstraints; import java.awt.GridBagLayo ...

  3. Swing JTable使用

    package cn.ychx; import java.awt.Dimension; import java.awt.Toolkit; import java.sql.Connection; imp ...

  4. 精通awk系列(4):awk用法入门

    回到: Linux系列文章 Shell系列文章 Awk系列文章 awk用法入门 awk 'awk_program' a.txt awk示例: # 输出a.txt中的每一行 awk '{print $0 ...

  5. [转帖]PG语法解剖--基本sql语句用法入门

    PG语法解剖--基本sql语句用法入门 https://www.toutiao.com/i6710897833953722894/ COPY 命令挺好的 需要学习一下. 原创 波波说运维 2019-0 ...

  6. Go之Logrus用法入门

    Go之Logrus用法入门 Logrus是Go (golang)的结构化日志程序,完全兼容标准库的API日志程序. Logrus is a structured logger for Go (gola ...

  7. AWK用法入门详解

    简介 awk是一个强大的文本分析工具,相对于grep的查找,sed的编辑,awk在其对数据分析并生成报告时,显得尤为强大.简单来说awk就是把文件逐行的读入,以空格为默认分隔符将每行切片,切开的部分再 ...

  8. Swing-JComboBox用法-入门

    JComboBox是Swing中的下拉菜单控件.它永远只能选中一个项目,然而比单选按钮节省空间.如果使用setEditable设置为true则内部选项的文本可以编辑,因此这种组件被称为组合框.注意,对 ...

  9. Swing-setBorder()用法-入门

    注:本文内容转自:Swing编程边框(Border)的用法总结.内容根据笔者理解稍有整理. 函数说明: public void setBorder(Border border) 设置此组件的边框.Bo ...

随机推荐

  1. C语言程序设计进阶 翁恺 第4周编程练习

    第4周编程练习 查看帮助 返回 第4周编程练习 依照学术诚信条款,我保证此作业是本人独立完成的. 温馨提示: 1.本次作业属于Online Judge题目,提交后由系统即时判分. 2.学生可以在作业 ...

  2. 以太网帧、TCP与UDP段以及IP数据报格式总结

    传输层及其以下的机制由内核提供,是操作系统的一部分,应⽤层由⽤户进程提供应⽤层数据通过协议栈发到⽹络上时,每层协议都要加上⼀个数据⾸部(header),称为封装.不同的协议层对数据包有不同的称谓,在传 ...

  3. CSS属性定义 文本修饰 边框效果 背景修饰

    一.CSS属性定义1.css颜色表示方法[重点]rgb(红绿蓝3个颜色通道 强度值为0-255)rgb(0,0,0)rgba(alpha a是透明度 值为0-1)rgba(123,123,123,0) ...

  4. Python模块----linecache

    Python标准库提供了一个有趣的模块:linecache模块.该模块用来从文件中读取任何的行,并且将这些lines使用缓存进行优化,常见的情况是从个大文件中读取指定的行.不过由于此模块使用内存进行缓 ...

  5. 【NO.3-2】Jmeter - 在Linux配置HOSTS的方法

    在Linux配置HOSTS 咱平时在Windows系统做web测试的时候需要修改HOSTS文件.Linux也一样. /*在Linux执行性能测试的时候,很容易忘记配置HOSTS,那么你发送的请求的响应 ...

  6. HTML5 新点总结-持续

    H5新的表单元素:datalist datalist的表现形式和原先的select标签相似,但是datalist想要发挥作用需要input标签的帮助:这样就可以在input标签中显示类似select下 ...

  7. 关于JS中涉及的常用类型转换及运算符表达式

    JS中的常用类型转换(一般用强制转换):1.强制转为整数:parseInt:写法:x = parseInt(x); 2.强制转换位小为:parseFloat:写法:x = parseFloat(x); ...

  8. 利用webpack构建vue项目

    快速搭建vue项目 一,确认自己有无搭建好node以及npm环境,这些是前提,具体安装方法可参考https://nodejs.org/en/. 二,开始构建项目. 第1步:新建一个文件夹,随意命名. ...

  9. 关于error C2872: 'LONG_PTR' : ambiguous symbol

    今天用VS2010创建了一个add-in工程,使用常量INVALID_HANDLE_VALUE时,编译器就提示如下错误: error C2872: 'LONG_PTR' : ambiguous sym ...

  10. MySQL的常用SQL语句.md

    修改密码 这是常见的大家一般都要用的 首先     安装成功了打开cmd --> mysql -u root -p -->输入你的密码     修改mysql root用户密码    格式 ...