浅析JTable与TableModel、TableCellRenderer、TableCellEditor接口——使用JComboBox显示单元格的值...

如同其它的Swing组件,JTable使用MVC(模型、试图、控制器)设计方式,将可视化组件(JTable实例)从其数据(TableModel实现)中分离出来。

·TableModel接口

1、TableModel为JTable提供

·显示的数据

·表格的维数

·表格中每一列所包含的数据类型

·应该显示的列标题

·是否允许编辑指定单元格的值

2、实现TableModel:

TableValues类

importjavax.swing.table.AbstractTableModel; /** * 注意:一般使用AbstractTableModel创建TableModel的实现,只有少量数据时使用DefaultTableModel, */ public class TableValues extendsAbstractTableModel{ privatestatic final long serialVersionUID = -8430352919270533604L; publicfinal static int NAME = 0; publicfinal static int GENDER = 1; publicfinal static String[] columnNames = {"姓名", "性别"}; publicObject[][] values = { {"Cannel_2020",true}, {"Lucy",false}, {"韩梅",false}, {"李雷",true}, {"Jim",true} }; publicint getColumnCount() { returnvalues[0].length; } publicint getRowCount() { returnvalues.length; } publicObject getValueAt(int rowIndex, int columnIndex) { returnvalues[rowIndex][columnIndex]; } /** * 设置列名 */ publicString getColumnName(int column){ returncolumnNames[column]; } }

SimpleTableTest类

import java.awt.BorderLayout; import java.awt.Container; import javax.swing.JFrame; import javax.swing.JScrollPane; import javax.swing.JTable; import javax.swing.table.TableColumn; import javax.swing.table.TableColumnModel; public class SimpleTableTest extendsJFrame{ privatestatic final long serialVersionUID = -4172876583187222326L; protected JTable table; publicSimpleTableTest(){ Containerpane = getContentPane(); pane.setLayout(newBorderLayout()); TableValuestv = new TableValues(); table= new JTable(tv); //设置行高 table.setRowHeight(30); //必须把table放入JScrollPane才会有列名出现 JScrollPanejsp = new JScrollPane(table); pane.add(jsp,BorderLayout.CENTER); } publicstatic void main(String[] args) { SimpleTableTeststt = new SimpleTableTest(); stt.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); stt.setSize(400,200); stt.setVisible(true); } }

运行结果:


·实现TableCellRenderer(单元格渲染器)接口

1、使表格“性别”一列的单元格出现JComboBox组件

GenderRenderer类

import java.awt.Component; import javax.swing.JComboBox; import javax.swing.JTable; import javax.swing.table.TableCellRenderer; public class GenderRenderer extendsJComboBox implements TableCellRenderer{ privatestatic final long serialVersionUID = -8624401777277852691L; publicGenderRenderer(){ super(); addItem("男"); addItem("女"); } publicComponent getTableCellRendererComponent(JTable table, Object value, booleanisSelected, boolean hasFocus, int row, int column) { if(isSelected){ setForeground(table.getForeground()); super.setBackground(table.getBackground()); }else{ setForeground(table.getForeground()); setBackground(table.getBackground()); } booleanisMale = ((Boolean)value).booleanValue(); setSelectedIndex(isMale? 0 : 1); returnthis; } }

2、SimpleTableTest类的构造函数改变如下:

public SimpleTableTest(){ setTitle("FromCannel_2020's blog(优快云)"); setLayout(newBorderLayout()); TableValuestv = new TableValues(); table= new JTable(tv); //设置行宽 table.setRowHeight(30); TableColumnModeltcm= table.getColumnModel(); TableColumntc = tcm.getColumn(TableValues.GENDER); //设置“性别”列的单元格渲染器(renderer) tc.setCellRenderer(newGenderRenderer()); //必须把table放入JScrollPane才会有列名出现 JScrollPanejsp = new JScrollPane(table); add(jsp,BorderLayout.CENTER); }

运行结果:


3、注意:渲染器实际上并没有像可视化组件添加到Container中那样添加到JTable实例中,即表格中不含有JComboBox实例。此时,是将唯一的JComboBox实例绘制(通过向paint()方法传递Graphics对象)到“性别”一列的每一个单元格所占用的区域中。

4、在TableValues添加如下代码(覆盖AbstractTableModel中的方法),使得JTable实例中单元格可以编辑:

/** * 设置单元格可以编辑 */ public booleanisCellEditable(int row, int column){ returntrue; }

然而此时对“性别”一列的单元格进行编辑,会出现如下情况:


这就得使用到单元格编辑器了。

·实现TableCellEditor(单元格编辑器)接口

1、

import java.awt.Component; import java.util.EventObject; import javax.swing.JComboBox; import javax.swing.JTable; importjavax.swing.event.CellEditorListener; import javax.swing.event.ChangeEvent; import javax.swing.event.EventListenerList; import javax.swing.table.TableCellEditor; public class GenderEditor extends JComboBoximplements TableCellEditor{ privatestatic final long serialVersionUID = 5860619160549087886L; //EventListenerList:保存EventListener 列表的类。 privateEventListenerList listenerList = new EventListenerList(); //ChangeEvent用于通知感兴趣的参与者事件源中的状态已发生更改。 privateChangeEvent changeEvent = new ChangeEvent(this); publicGenderEditor(){ super(); addItem("男"); addItem("女"); //请求终止编辑操作可以包含单元格的JTable收到,也可以从编辑器组件本身(如这里的JComboBox)获得 /*addActionListener(newActionListener(){ publicvoid actionPerformed(ActionEvent e) { System.out.println("ActionListener"); //如同stopCellEditing,都是调用fireEditingStopped()方法 fireEditingStopped(); } });*/ } publicvoid addCellEditorListener(CellEditorListener l) { listenerList.add(CellEditorListener.class,l); } publicvoid removeCellEditorListener(CellEditorListener l) { listenerList.remove(CellEditorListener.class,l); } privatevoid fireEditingStopped(){ CellEditorListenerlistener; Object[]listeners = listenerList.getListenerList(); for(inti = 0; i < listeners.length; i++){ if(listeners[i]== CellEditorListener.class){ //之所以是i+1,是因为一个为CellEditorListener.class(Class对象), //接着的是一个CellEditorListener的实例 listener= (CellEditorListener)listeners[i+1]; //让changeEvent去通知编辑器已经结束编辑 //在editingStopped方法中,JTable调用getCellEditorValue()取回单元格的值, //并且把这个值传递给TableValues(TableModel)的setValueAt() listener.editingStopped(changeEvent); } } } publicvoid cancelCellEditing() { } /** * 编辑其中一个单元格,再点击另一个单元格时,调用。-------------!!!!! */ publicboolean stopCellEditing() { //可以注释掉下面的fireEditingStopped();,然后在GenderEditor的构造函数中把 //addActionListener()的注释去掉(这时请求终止编辑操作从JComboBox获得), System.out.println("编辑其中一个单元格,再点击另一个单元格时,调用。"); fireEditingStopped();//请求终止编辑操作从JTable获得 returntrue; } /** * 为一个单元格初始化编辑时,getTableCellEditorComponent被调用 */ publicComponent getTableCellEditorComponent(JTable table, Object value, booleanisSelected, int row, int column) { booleanisMale = ((Boolean)value).booleanValue(); setSelectedIndex(isMale? 0 : 1); returnthis; } /** * 询问编辑器它是否可以使用 anEvent 开始进行编辑。 */ publicboolean isCellEditable(EventObject anEvent) { returntrue; } /** * 如果应该选择正编辑的单元格,则返回true,否则返回 false。 */ publicboolean shouldSelectCell(EventObject anEvent) { returntrue; } /** * 返回值传递给TableValue(TableModel)中的setValueAt()方法 */ publicObject getCellEditorValue() { returnnew Boolean(getSelectedIndex() == 0 ? true : false); } }

2、SimpleTableTest类的构造函数中

tc.setCellRenderer(new GenderRenderer());

后面加入:

//设置“性别”列的单元格编辑器(editor) tc.setCellEditor(new GenderEditor());

运行结果:


3、还有一点别忘了再在TableValues加入如下代码(原因:看第4的最后一点

/** * 单元格被编辑完后,调用此方法更新值 */ publicvoid setValueAt(Object value, int row, int column){ values[row][column]= value; }

4、GenderEditor类的工作流程:

1)、调用TableCellEditor接口中的getTableCellEditorComponent()方法初始化编辑

2)、编辑当前的单元格,再点击另一个单元格时,调用CellEditor中的stopCellEditing(),通过fireEditingStopped()调用到editingStopped()。

3)、在editingStopped方法中,JTable调用getCellEditorValue()取回单元格的值,并且把这个值传递给TableValues(TableModel)的setValueAt()

 

转载于:https://www.cnblogs.com/myittec/archive/2012/02/17/2392761.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值