引章小姐 发表于 2009-2-5 10:37:11

思维要向上,研究要向底层

最近产品需要在JTable中显示JComboBox,It‘s easy,
    在java application中,如果swing界面需要在表格中显示JComboBox,通常会使用JTable 的Editor方法,
    但是表格中有几列的值需要根据JComboBox的选择而改变,这几列是否可以编辑也要根据JComboBox的选择而改变,
    首先的思路是表格加入Jcombobox之后,给JComboBox加监听,addActionListener,或者addItemListener,都可以,
    为了专业一点,还是添加ItemListener比较好,因为这个是JComboBox常用的。
    思路就是这样,鼠标点击表格的一行,得到表格的选中行,从JComboBox的监听中得到选中的Item,
    根据选择判断是否向固定列赋值,
    编码:
    为了灵活首先要继承一个DefaultCellEditor
    public class ComboEditor extends DefaultCellEditor
    {
            public ComboEditor()   {
               super(new JComboBox());
             }
            public boolean isCellEditable(EventObject eventObject) {
                      return true;
            }
   }
    JTable m_table = new JTable()
    ComboEditor editorSignalType = null;
    JComboBox boxSignalType = null;
      editorSignalType = getComboEditor();
          m_table.getColumnModel().getColumn(0).setCellEditor(editorSignalType);
         boxSignalType.addItemListener(this);
   
    private ComboEditor getComboEditor() {
                   ComboEditor editor = new ComboEditor();
                  boxSignalType = (JComboBox) ((ComboEditor) editor).getComponent();
                  boxSignalType.removeAllItems();
                      //给JComboBox赋值   ........    //
                  return editor;
    }
    JComboBox事件处理:
    public void itemStateChanged(ItemEvent e) {
                     Object[] obj = item.getItemSelectable().getSelectedObjects();
                      int selectRow = m_table.getSelectedRow();
                     //向表格赋值
                         setTableRowData(obj.toString(),selectRow);
   }
    ……编译ing
    调试ing
    问题出现了,selectRow不是当前选中的行,是前一个选中的行号,为什么会出现这种状况?       原因是点击表格中的JComboBox时,ItemListener先捕捉到事件,执行itemStateChanged时候JTable还没有选中,         selectRow是-1或者前次选中的行数,怎么办?            修改思路,让程序先得到选中的表格行号,在去执行JComboBox的监听事件:具体的实现方法呢?             众所周知,软件的实现有很多种方法,如果是一个沉迷界面乐趣的人方法大概会这样:
    A 给表格添加mouseListener,
    B 点击表格时先得到选中行,
    C 给JComboBox添加监听器,
    D 触发JComboBox事件执行事件处理方法,
    E 移除JComboBox添加监听器
               这是一个使用java GUI 熟练的人的思路,很酷很复杂,多个监听混在一起复杂度大大增加,实际也是这样,       调试相当的麻烦,并不能很好的达到目的,这个方法还有一个缺点,用很表层的方法来处理问题,没有认识到javaGUI的设计本质。       该可以想到的,软件的设计不会让使用者用一个很复杂的方法来实现一个功能,应该有更好的方法,那么该如何实现?         这时需要安静下来想一下:JTable Editer ,它的功能是把JComboBox放到JTable的一个格内,既然已经放进去了,那么CellEditor      一定已经得到这个表格单元格的行和列了,显然用m_table.getSelectedRow();是错误的,应该向swing的底层实现思考,   看看DefaultCellEditor的源码,不难找到 int column ,int row的字样,把他们得到取出来如何?
    修改之前的实现:
    修改 ComboEditor:
    public class ComboEditor extends DefaultCellEditor
    {
    public ComboEditor()   {
         super(new JComboBox());
    }
      public boolean isCellEditable(EventObject eventObject) {   return true;   }
   //**第二次修改添加*********************************************
       private int row;
   private int column;
    public Component getTableCellEditorComponent(   JTable table, Object value,   boolean isSelected,   int row,   int column)
   {
          this.row = row;
          this.column = column;
         return super.getTableCellEditorComponent(table,value,isSelected,row,column);
   }
       public int getRow(){
             return row;
      }
       public int getColumn(){
            return column;
      }
    //**************************************************
    }
    修改 JComboBox事件处理:
    public void itemStateChanged(ItemEvent e) {
          Object[] obj = item.getItemSelectable().getSelectedObjects();
         int selectRow = editorSignalType.getRow();
            //向表格赋值
             setTableRowData(obj.toString(),selectRow);
    }
    ……编译ing
    调试ing
    OK 所得到的行号就是点击JComboBox的那行,这个思路是对的,而且简单的多,问题解决了。
    总结:
    解决复杂的难题需要提升思考的高度,分析java的源码,根据需要写出自己需要的东西,
    最好理解java类架构的原理,从思维方面解决遇到难题,
    提升思维高度,研究底层代码。
页: [1]
查看完整版本: 思维要向上,研究要向底层