前几篇文章介绍了JTable的基本用法,本文实现一个简单的JTable,算是前文的一个总结,并造福供拷贝党们。

Swing-JTable用法-入门

Swing-JTable的渲染器与编辑器使用demo

Swing-JTable检测单元格数据变更事件

一、主要功能

1.数据的增删改;

2.渲染器:“Vegetarian”列存放布尔值,以checkBox形式显示;“Sport”列存放字符串,以comboBox形式显示;

3.编辑器:“Name”的编辑器实现一个按钮,按下时弹出对话框;

4.ToolTip:各列和各单元格均具有自己的ToolTip,且单元格ToolTip与其值相关;

5.事件:检测单元格值的变更,并输出旧值、新值和单元格坐标。

二、程序设计

本程序根据功能可分为6部分,以6个类来实现,分别是:

Gui.java:实现GUI,成员有:1个JTable,2个按钮;

MyJTable.java:继承自JTable,重载2个方法:getToolTipText和createDefaultTableHeader,分别实现单元格和表头的toolTip;

MyTableModel.java:继承自DefaultTableModel,重载1个方法:getColumnClass,实现布尔值的checkBox形式显示。表格的基本功能均已被DefaultTableModel类实现,直接使用就好。如果你还需要对单元格可访问性等细节进行精确控制,可以重载相关方法。

TableCellListener.java:实现对单元格数据变更的检测。这是通过表格的addPropertyChangeListener方法实现的,而不是基于tableModel的addTableModelListener方法。后者的不足之处在前文中已经分析。

ButtonEditor.java:实现一个基于按钮的编辑器,被按下时弹出对话框;

ButtonRenderer.java:实现一个渲染器,可定制单元格的配色。

三、程序代码

Gui.java

package DefaultTableModelDemo;
import java.awt.Dimension;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JComponent;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextField;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.TableColumn;
import JButtonTableExample.ButtonEditor;
import JButtonTableExample.ButtonRenderer; public class Gui extends JPanel { private Object[] tmpRow = {"tmpName", "tmpDescription"};
private MyJTable table;
private JButton addBtn;
private JButton delBtn;
private MyTableModel model ; public Gui() {
table = new MyJTable();
table.setPreferredScrollableViewportSize(new Dimension(500, 300));
table.setFillsViewportHeight(true); //Create the scroll pane and add the table to it.
JScrollPane scrollPane = new JScrollPane(table);
//scrollPane.setPreferredSize(new Dimension(500, 600));
//scrollPane.set
//Add the scroll pane to this panel.
add(scrollPane);
//set tableModel and data
model = new MyTableModel();
String[] columnNames = {"Name",
"Description",
"Sport",
"# of Years",
"Vegetarian"};
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)}
};
model.setDataVector(data, columnNames);
table.setModel(model);
//添加渲染器
table.getColumn("Name").setCellRenderer(new ButtonRenderer());
//添加编辑器
table.getColumn("Name").setCellEditor( new ButtonEditor());
//添加按钮
addBtn = new JButton("增加");
addBtn.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
model.addRow(tmpRow);
}
}); delBtn = new JButton("删除");
delBtn.addActionListener(new ActionListener() { @Override
public void actionPerformed(ActionEvent arg0) {
// TODO Auto-generated method stub
int rowIndex = table.getSelectedRow();
if(rowIndex != -1)
model.removeRow(rowIndex);
}
}); add(addBtn);
add(delBtn); addDataChangeListener(); //设置列
setSportsColumn();
} private void setSportsColumn(){
String [] itmes = {"Snowboarding", "Rowing", "Knitting", "Speed reading", "Pool"};
JComboBox<String> comboBox = new JComboBox<String>(itmes);
DefaultTableCellRenderer renderer =
new DefaultTableCellRenderer();
renderer.setToolTipText("Click for combo box");
setColumn("Sport", comboBox, renderer);
TableColumn col = table.getColumn("Sport");
//setToolTipText("favorit sport is " + );
} public void setColumn(String colName, Object editor, Object renderer) {
int index = table.getColumnModel().getColumnIndex(colName);
TableColumn modeColumn = table.getColumnModel().getColumn(index);
if (editor instanceof JComponent) {
setEditor(modeColumn, (JComponent)editor);
}
else if (editor instanceof DefaultCellEditor) {
modeColumn.setCellEditor((DefaultCellEditor)editor);
} if (renderer instanceof DefaultTableCellRenderer) {
modeColumn.setCellRenderer((DefaultTableCellRenderer)renderer);
}
else if (renderer instanceof ButtonRenderer) {
modeColumn.setCellRenderer((ButtonRenderer)renderer);
}
} protected void setEditor(TableColumn column, JComponent component){
if(component instanceof JTextField )
column.setCellEditor(new DefaultCellEditor((JTextField) component));
else if(component instanceof JComboBox )
column.setCellEditor(new DefaultCellEditor((JComboBox<String>) component));
else if(component instanceof JCheckBox )
column.setCellEditor(new DefaultCellEditor((JCheckBox) component));
} private void addDataChangeListener(){
//检测单元格数据变更
Action action = new AbstractAction()
{
public void actionPerformed(ActionEvent e)
{
TableCellListener tcl = (TableCellListener)e.getSource();
int row = tcl.getRow();
int col = tcl.getColumn();
Object oldValue = tcl.getOldValue();
//if(oldValue == null)
//oldValue = "";
Object newValue = tcl.getNewValue();
//if(newValue == null)
//newValue = "";
System.out.printf("cell changed at [%d,%d] : %s -> %s%n",row, col, oldValue, newValue);
}
};
@SuppressWarnings("unused")
TableCellListener tcl1 = new TableCellListener(table, action);
System.out.printf("cell changed%n");
} private static void createAndShowGUI() {
//Create and set up the window.
JFrame frame = new JFrame("Gui");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); //Create and set up the content pane.
Gui newContentPane = new Gui();
newContentPane.setOpaque(true); //content panes must be opaque
frame.setContentPane(newContentPane); //Display the window.
frame.pack();
frame.setVisible(true);
} public static void main(String[] args) {
//Schedule a job for the event-dispatching thread:
//creating and showing this application's GUI.
javax.swing.SwingUtilities.invokeLater(new Runnable() {
public void run() {
createAndShowGUI();
}
});
}
}

MyTableModel.java

package DefaultTableModelDemo;

import javax.swing.table.DefaultTableModel;

public class MyTableModel extends DefaultTableModel{

    @Override
public Class<?> getColumnClass(int columnIndex) {
if (columnIndex == 4)
return Boolean.class;
return super.getColumnClass(columnIndex);
}
}

MyJTable.java

package DefaultTableModelDemo;

import java.awt.event.MouseEvent;

import javax.swing.JTable;
import javax.swing.table.JTableHeader;
import javax.swing.table.TableModel; public class MyJTable extends JTable{ protected String[] columnToolTips = {null,
null,
"The person's favorite sport to participate in is : ",
"The number of years the person has played the sportis : ",
"If checked, the person eats no meat"}; //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(rowIndex < 0)
{
//System.out.printf("abnormal rowIndex: %n", rowIndex);
return null;
} if (realColumnIndex == 2) { //Sport column
tip = columnToolTips[2]
+ getValueAt(rowIndex, colIndex);
}
else if (realColumnIndex == 3) { //Years column
tip = columnToolTips[3] + 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 {
//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;
} //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];
}
};
} }

TableCellListener.java

package DefaultTableModelDemo;
import java.awt.event.*;
import javax.swing.*;
import java.beans.*; /*
* This class listens for changes made to the data in the table via the
* TableCellEditor. When editing is started, the value of the cell is saved
* When editing is stopped the new value is saved. When the oold and new
* values are different, then the provided Action is invoked.
*
* The source of the Action is a TableCellListener instance.
*/
public class TableCellListener implements PropertyChangeListener, Runnable
{
private JTable table;
private Action action; private int row;
private int column;
private Object oldValue;
private Object newValue; /**
* Create a TableCellListener.
*
* @param table the table to be monitored for data changes
* @param action the Action to invoke when cell data is changed
*/ public TableCellListener(JTable table, Action action)
{
this.table = table;
this.action = action;
this.table.addPropertyChangeListener( this );
} /**
* Create a TableCellListener with a copy of all the data relevant to
* the change of data for a given cell.
*
* @param row the row of the changed cell
* @param column the column of the changed cell
* @param oldValue the old data of the changed cell
* @param newValue the new data of the changed cell
*/
private TableCellListener(JTable table, int row, int column, Object oldValue, Object newValue)
{
this.table = table;
this.row = row;
this.column = column;
this.oldValue = oldValue;
this.newValue = newValue;
} /**
* Get the column that was last edited
*
* @return the column that was edited
*/
public int getColumn()
{
return column;
} /**
* Get the new value in the cell
*
* @return the new value in the cell
*/
public Object getNewValue()
{
return newValue;
} /**
* Get the old value of the cell
*
* @return the old value of the cell
*/
public Object getOldValue()
{
return oldValue;
} /**
* Get the row that was last edited
*
* @return the row that was edited
*/
public int getRow()
{
return row;
} /**
* Get the table of the cell that was changed
*
* @return the table of the cell that was changed
*/
public JTable getTable()
{
return table;
}
//
// Implement the PropertyChangeListener interface
//
@Override
public void propertyChange(PropertyChangeEvent e)
{
// A cell has started/stopped editing if ("tableCellEditor".equals(e.getPropertyName()))
{
if (table.isEditing()){
//System.out.printf("tableCellEditor is editing..%n");
processEditingStarted();
}
else{
//System.out.printf("tableCellEditor editing stopped..%n");
processEditingStopped();
} }
} /*
* Save information of the cell about to be edited
*/
private void processEditingStarted()
{
// The invokeLater is necessary because the editing row and editing
// column of the table have not been set when the "tableCellEditor"
// PropertyChangeEvent is fired.
// This results in the "run" method being invoked SwingUtilities.invokeLater( this );
}
/*
* See above.
*/
@Override
public void run()
{
row = table.convertRowIndexToModel( table.getEditingRow() );
column = table.convertColumnIndexToModel( table.getEditingColumn() );
oldValue = table.getModel().getValueAt(row, column);
//这里应对oldValue为null的情况做处理,否则将导致原值与新值均为空时仍被视为值改变
if(oldValue == null)
oldValue = "";
newValue = null;
} /*
* Update the Cell history when necessary
*/
private void processEditingStopped()
{
newValue = table.getModel().getValueAt(row, column);
//这里应对newValue为null的情况做处理,否则后面会抛出异常
if(newValue == null)
newValue = "";
// The data has changed, invoke the supplied Action
if (! newValue.equals(oldValue))
{
// Make a copy of the data in case another cell starts editing
// while processing this change TableCellListener tcl = new TableCellListener(
getTable(), getRow(), getColumn(), getOldValue(), getNewValue()); ActionEvent event = new ActionEvent(
tcl,
ActionEvent.ACTION_PERFORMED,
"");
action.actionPerformed(event);
}
}
}

ButtonEditor.java

package JButtonTableExample;

import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.DefaultCellEditor;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComponent;
import javax.swing.JOptionPane;
import javax.swing.JTable; public class ButtonEditor extends DefaultCellEditor {
protected JButton button;//represent the cellEditorComponent
private String cellValue;//保存cellEditorValue public ButtonEditor() {
super(new JCheckBox());
button = new JButton();
button.setOpaque(true);
button.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
JOptionPane.showMessageDialog(button, cellValue + ": Ouch!");
//刷新渲染器
fireEditingStopped();
}
});
} public JComponent getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
//value 源于单元格数值
cellValue = (value == null) ? "" : value.toString();
return button;
} public Object getCellEditorValue() {
return new String(cellValue);
}
}

ButtonRenderer.java

package JButtonTableExample;

import java.awt.Color;
import javax.swing.JButton;
import javax.swing.JComponent;
import javax.swing.JTable;
import javax.swing.table.TableCellRenderer; public class ButtonRenderer extends JButton implements TableCellRenderer { public JComponent getTableCellRendererComponent(JTable table, Object value,
boolean isSelected, boolean hasFocus, int row, int column) {
//value 源于editor
String text = (value == null) ? "" : value.toString();
//按钮文字
setText(text);
//单元格提示
setToolTipText(text);
//背景色
setBackground(Color.BLACK);
//前景色
setForeground(Color.green);
return this;
}
}

运行效果如下:

JTable用法-实例的更多相关文章

  1. php中的curl使用入门教程和常见用法实例

    摘要: [目录] php中的curl使用入门教程和常见用法实例 一.curl的优势 二.curl的简单使用步骤 三.错误处理 四.获取curl请求的具体信息 五.使用curl发送post请求 六.文件 ...

  2. 上传文件及$_FILES的用法实例

    Session变量($_SESSION):�php的SESSION函数产生的数据,都以超全局变量的方式,存放在$_SESSION变量中.1.Session简介SESSION也称为会话期,其是存储在服务 ...

  3. C++语言中cin cin.getline cin.get getline gets getchar 的用法实例

    #include <iostream> #include <string> using namespace std; //关于cin cin.getline cin.get g ...

  4. Union all的用法实例sql

    ---Union all的用法实例sqlSELECT TOP (100) PERCENT ID, bid_user_id, UserName, amount, createtime, borrowTy ...

  5. 【转】javascript入门系列演示·三种弹出对话框的用法实例

    对话框有三种 1:只是提醒,不能对脚本产生任何改变: 2:一般用于确认,返回 true 或者 false ,所以可以轻松用于 if...else...判断 3: 一个带输入的对话框,可以返回用户填入的 ...

  6. php strpos 用法实例教程

    定义和用法该strpos ( )函数返回的立场,首次出现了一系列内部其他字串. 如果字符串是没有发现,此功能返回FALSE . 语法 strpos(string,find,start) Paramet ...

  7. 【JSP】三种弹出对话框的用法实例

    对话框有三种 1:只是提醒,不能对脚本产生任何改变: 2:一般用于确认,返回 true 或者 false ,所以可以轻松用于 if...else...判断 3: 一个带输入的对话框,可以返回用户填入的 ...

  8. python多线程threading.Lock锁用法实例

    本文实例讲述了python多线程threading.Lock锁的用法实例,分享给大家供大家参考.具体分析如下: python的锁可以独立提取出来 mutex = threading.Lock() #锁 ...

  9. jQuery中on()方法用法实例详解

    这篇文章主要介绍了jQuery中on()方法用法,实例分析了on()方法的功能及各种常见的使用技巧,并对比分析了与bind(),live(),delegate()等方法的区别,需要的朋友可以参考下 本 ...

随机推荐

  1. 【机器学习笔记之三】CART 分类与回归树

    本文结构: CART算法有两步 回归树的生成 分类树的生成 剪枝 CART - Classification and Regression Trees 分类与回归树,是二叉树,可以用于分类,也可以用于 ...

  2. 用ubuntu的grpb2引导Remix OS

    Remix OS游戏版,这里下载:http://youxi.jide.com/ 安装简单.我这里要解决的是安装后用ubunu的grub2菜单去引导它. 方法如下: 进入ubuntu系统里修改其grub ...

  3. 用github展示前端页面

    今天尝试了一下使用github展示前端页面,还是比较简单的,平时做一些小的demo时,可以用这个方法展示自己的页面,在此记录下方法. 首先打开自己的github项目仓库,比如   https://gi ...

  4. 关于Thread类的简单使用

    线程:线程也被称为轻量级进程,进程和线程都提供一个执行环境,但创建一个新的线程比创建一个新的进程资源要少得多 线程存在进程里,也就是说一个进程至少包括一个线程 线程共享进程的资源,包括内存和打开的文件 ...

  5. Windows Firewall Setting

    If our web site hosted on web server canot be accessed by other computer by public network, one of t ...

  6. Linux下自动备份MySQL数据库并上传到远程FTP服务器

    Linux下自动备份MySQL数据库并上传到远程FTP服务器且删除指定日期前的备份Shell脚本 说明:  1.备份MySQL数据库存放目录/var/lib/mysql下面的xshelldata数据库 ...

  7. VMware Workstation 12 Player之安装林耐斯-Linux Red Hat 7 -系统

    Linux系统之Red Hat 7 安装笔记... Red Hat(红帽)公司(NYSE:RHT)是一家开源解决方案供应商,也是标准普尔500指数成员.总部位于美国北卡罗来纳州的罗利市,截止2015年 ...

  8. 区别jquery对象和dom对象及转换方法

    一.jquery对象 由$() 获取,例如 var div = $("#id"); 这个div是jquery对象,它里面没有dom对象自带的方法.常见的dom对象自带的方法, 例如 ...

  9. CSS:a:link;visited;hover;active解释及正确顺序

    a:link 选择器设置指向普通的.未被访问页面的链接的样式, a:visited 选择器用于设置指向已被访问的页面的链接, a:active 选择器用于活动链接, a:hover 选择器用于选择鼠标 ...

  10. LaTeX的表格插入与排版

    关于LaTex中的图表问题的几篇有用的文章 Graphics and Colour with LaTeX  有关在LaTex中插图和使用颜色的在线指导. Figure'ing and Picture' ...