zoukankan      html  css  js  c++  java
  • 浅析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()

     

  • 相关阅读:
    爬取卡通图片
    python 列表生成式
    python 装饰器
    python 协程 and 进程
    ssh登录缓慢问题
    解决 input 元素点击有蓝色边框的问题
    JavaScript面试题总结系列(九)
    JavaScript面试题总结系列(八)
    JavaScript面试题总结系列(七)
    JavaScript面试题总结系列(六)
  • 原文地址:https://www.cnblogs.com/gwq369/p/5351869.html
Copyright © 2011-2022 走看看