如同其它的Swing组件,JTable使用MVC(模型、试图、控制器)设计方式,将可视化组件(JTable实例)从其数据(TableModel实现)中分离出来。
·TableModel接口
1、TableModel为JTable提供
·显示的数据
·表格的维数
·表格中每一列所包含的数据类型
·应该显示的列标题
·是否允许编辑指定单元格的值
2、实现TableModel:
TableValues类
- importjavax.swing.table.AbstractTableModel;
-
-
-
- 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);
-
- 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(CSDN)");
- setLayout(newBorderLayout());
- TableValuestv = new TableValues();
- table= new JTable(tv);
-
- table.setRowHeight(30);
-
- TableColumnModeltcm= table.getColumnModel();
- TableColumntc = tcm.getColumn(TableValues.GENDER);
-
- tc.setCellRenderer(newGenderRenderer());
-
-
- 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;
-
- privateEventListenerList listenerList = new EventListenerList();
-
- privateChangeEvent changeEvent = new ChangeEvent(this);
- publicGenderEditor(){
- super();
- addItem("男");
- addItem("女");
-
-
-
-
-
-
-
-
-
- }
- 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){
-
-
- listener= (CellEditorListener)listeners[i+1];
-
- <span style="white-space:pre"> </span>
-
- listener.editingStopped(changeEvent);
- }
- }
- }
- publicvoid cancelCellEditing() {
- }
-
-
-
- publicboolean stopCellEditing() {
-
-
- System.out.println("编辑其中一个单元格,再点击另一个单元格时,调用。");
- fireEditingStopped();
- returntrue;
- }
-
-
-
- publicComponent getTableCellEditorComponent(JTable table, Object value,
- booleanisSelected, int row, int column) {
- booleanisMale = ((Boolean)value).booleanValue();
- setSelectedIndex(isMale? 0 : 1);
- returnthis;
- }
-
-
-
- publicboolean isCellEditable(EventObject anEvent) {
- returntrue;
- }
-
-
-
- publicboolean shouldSelectCell(EventObject anEvent) {
- returntrue;
- }
-
-
-
-
- publicObject getCellEditorValue() {
- returnnew Boolean(getSelectedIndex() == 0 ? true : false);
- }
- }
2、把SimpleTableTest类的构造函数中
- tc.setCellRenderer(new GenderRenderer());
后面加入:
-
- 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()