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()

     

  • 相关阅读:
    bzoj-2748 2748: [HAOI2012]音量调节(dp)
    bzoj-2338 2338: [HNOI2011]数矩形(计算几何)
    bzoj-3444 3444: 最后的晚餐(组合数学)
    codeforces 709E E. Centroids(树形dp)
    codeforces 709D D. Recover the String(构造)
    codeforces 709C C. Letters Cyclic Shift(贪心)
    codeforces 709B B. Checkpoints(水题)
    codeforces 709A A. Juicer(水题)
    Repeat Number
    hdu 1003 Max Sum (动态规划)
  • 原文地址:https://www.cnblogs.com/gwq369/p/5351869.html
Copyright © 2011-2022 走看看