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

转载:http://www.cnblogs.com/langtianya/archive/2012/09/04/2671173.html

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

【github URL:https://github.com/langtianya】 【Other Blog: my.csdn.net/ouchuquan 和 my.oschina.net/u/187589 和 blog.sina.com.cn/u/2430843520】

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

·TableModel接口

1、TableModel为JTable提供

·显示的数据

·表格的维数

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

·应该显示的列标题

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

2、实现TableModel:

TableValues类

import javax.swing.table.AbstractTableModel;
/**  
 *     注意:一般使用AbstractTableModel创建TableModel的实现,只有少量数据时使用DefaultTableModel,
 */
public class TableValues extends AbstractTableModel{
         private static final long serialVersionUID = -8430352919270533604L;
         public final static int NAME = 0;
         public final static int GENDER = 1;
         public final static String[] columnNames = {"姓名", "性别"};
         public Object[][] values = {
                            {"Cannel_2020",true},
                            {"Lucy",false},
                            {"韩梅",false},
                            {"李雷",true},
                            {"Jim",true}
         };
         publicint getColumnCount() {
                   return  values[0].length;
         }
         publicint getRowCount() {
                   return values.length;
         }
         public Object getValueAt(int rowIndex, int columnIndex) {
                   return values[rowIndex][columnIndex];
         }

/**
          * 获取列名
          */
         publicString getColumnName(int column){
                   return columnNames[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 extends JFrame{
        
         private static final long serialVersionUID = -4172876583187222326L;
         protected JTable table;
         public SimpleTableTest(){
                   Container pane = getContentPane();
                   pane.setLayout(newBorderLayout());

TableValues tv =  new TableValues();
                   table= new JTable(tv);

//设置行高
                   table.setRowHeight(30);
                   //必须把table放入JScrollPane才会有列名出现
                   JScrollPane jsp = 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);
                   //设置“性别”列的单元格渲染器(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去通知编辑器已经结束编辑
                           <span style="white-space:pre"> </span>     //在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()

时间: 2024-10-11 22:11:27

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

JTable 单元格合并 【转】

单元格合并 一.单元格合并.(1)我们可以使用Jtable的三个方法:getCellRect(),columnAtPoint(),and rowAtPoint().第一个方法返回一个单元格的边界(Rectangle类),第二.三个方法分别返回屏幕指定位置的列和行.为了实现单元格合并,我们需要重载(overwrite)这三个方法. (2)另外我们需要找出渲染Jtable的ComponentUI对象,并且修改它以达到我们的目的. (3)创建新的类记录单元格合并情况的数据模型,它要包涵一个方法来取得单

通过自定义单元格渲染器在Jtable中显示超链接

转载:http://www.tuicool.com/articles/qE7FNv 在JTable中自定义单元格渲染器是非常简单和容易的.对于单元格渲染器来说,它的主要任务就是为目标单元格返回一个Component对象,以呈现其内容.说到Component,就应该豁然开朗了,因为在Swing中,所有可在屏幕上显示的图形控件都是Component的直接或间接子类,也就是说,理论上你可以在JTable单元格中显示任意图形控件! 当然,实际上有一些控件是不能在单元格中显示的,比如JFrame这样的独立

在JTable单元格上 加入组件,并赋予可编辑能力 [转]

表格(单元格放置组件) 对于JTable单元格的渲染主要是通过两个接口来实现的,一个是TableCellRenderer另一个是TableCellEditor,JTable默认是用的是DefaultCellRenderer和DefaultCellEditor,这两个都是在类似JTextfield的一个JComponent的基础上来实现的,如果我们需要在JTable的单元格内放置特殊的控件或者绘制出特殊的效果,就要实现TableCellRenderer和TableCellEditor接口,在其上绘

【代码笔记】Java连连看项目的实现(2)——JTable 、TableModel的使用

博客有时间就写写,所以一篇可能会拆成很多篇,写完后计划再合在一起. 首先肯定是要实现连连看的界面. 先准备连连看要的图片.. “LianLianKan”就是项目名称. 当然,如果小白看我的博客想学到什么,我会说还是放弃,因为文字描述会忽视很多细节,而细节决定bug…… 所以,包括以前的和以后的,博文都会是给自己看看或者内行触类旁通的,也就是——笔记. 我也是今天才明白博文的真正意义吧,所以以后的博文风格会大改……尽量会用自己语言风格来描述以便自己能看懂. 废话少说,现在的第2步: 创建数组,一个

【代码笔记】Java连连看项目的实现(1)——JTable 、TableModel的使用

javax.swing.table.TableModel和javax.swing.JTable JTable .TableModel是Java里面画表格的包. TableModel:为Table提供显示数据.表格维数.表格中显示数据类  型.列标题等Table需要显示的一些属性 JTable:提供表格本身的属性和操作,比如表格的样式.行高.背景.行选中属性等 JTable相当于网页,模特:TableModel相当于服务器,衣服. JTable .TableModel 两者是相互依赖的关系(等于B

请教 JTable 里的单元格如何使得双击进入单元格后,单元格的内容处于全选中状态

http://bbs.csdn.net/topics/390195204 ———————————————————————————————————————— java 达人, 最近在开发一个 java 模块,用到了 JTable.现在对 JTable 里的单元格的操作中,在双击进入单元格后,单元格的内容不是全选中状态. 请问有啥办法使得双击进入单元格后,单元格的内容处于全选中状态?如下面的图片所示 十分感谢! 下面是已经写好的代码: Java code? 1 2 3 4 5 6 7 8 9 10

Swing中使用JTable动态获取数据库中的数据并显示

笔者注:本文供新手学习使用,若有一定基础,可以直接看3! 1.创建数据库: /* Navicat MySQL Data Transfer Source Server : aa Source Server Version : 50519 Source Host : localhost:3306 Source Database : test Target Server Type : MYSQL Target Server Version : 50519 File Encoding : 65001 D

iOS中自定义UIView(用接口获取Lable和TextFile中的值)

NSArray *arrayText = @[@"用户名",@"密码",@"确认密码",@"手机号",@"邮箱"]; NSArray *placeholders = @[@"请输入用户名",@"请输入密码",@"请确认密码",@"请输入手机号",@"请输入邮箱"]; NSInteger y = 30; for

TCP发送接口(如send(),write()等)的返回值与成功发送到接收端的数据量无直接关系

原文链接: http://blog.csdn.net/ordeder/article/details/17240221 1. TCP发送接口:send() TCP发送数据的接口有send,write,sendmsg.在系统内核中这些函数有一个统一的入口,即sock_sendmsg().由于TCP是可靠传输,所以对TCP的发送接口很容易产生误解,比如sn = send(...); 错误的认为sn的值是表示有sn个字节的数据已经发送到了接收端.其实真相并非如此. 我们知道,TCP的发送和接收在在内核