围观DefaultCellEditor之源码

 问题背景:

      项目中要实现自己的JTable的CellEditor,easy!参考官方例子代码,也就是extends AbstractCellEditor重写里面的getTableCellEditorComponent的方法,可是问题来了,实现了自己的cellEditor,但是其行为为只要点击cell,马上就cell就处于编辑状态,如何实现像默认的情况下,双击启动编辑模式呢?

解决办法:

      也许处于惯性思维方式下,想都没有想,便F3到了DefaultCellEditor源码,便开始寻找原始解决方案!

     

  /**
     * An integer specifying the number of clicks needed to start editing.
     * Even if <code>clickCountToStart</code> is defined as zero, it
     * will not initiate until a click occurs.
     */
    protected int clickCountToStart = 1;

 

     看到这条语句,心中窃喜,用大腿想都想得到,它就是控制点击次数,从而控制编译器启动的.

   

 public DefaultCellEditor(final JTextField textField) {
        editorComponent = textField;
	this.clickCountToStart = 2;
        delegate = new EditorDelegate() {
            public void setValue(Object value) {
		textField.setText((value != null) ? value.toString() : "");
            }

	    public Object getCellEditorValue() {
		return textField.getText();
	    }
        };
	textField.addActionListener(delegate);
    }

 

    这个类构造器让我迷惑了好久,原来它里面还有个内部类,这看起来就很复杂了!

   习惯了过程化编程思维方式的我,看到这句余音缭绕,弯弯曲曲的语句,会本能的放弃,纵使它实际是很简单,很优雅!

   放弃之后我选择了去寻找别的解决方式,google了,在尝试了别的比如有一条无所不能的语句,就可以达到目的的,或者

   就万能的语句,最终还是硬着头皮看它是怎么实现的.

    

    这次好像有点感觉了

  

protected EditorDelegate delegate;

 

  delegate的重复出现,让我好像想到了什么,对了,就是代理,难道这么个短小的几行和一个类,还用了代理模式?

  不用怀疑了,它确实用了代理模式!

   看了N多设计模式书的我,觉得那就更应该欣赏下这些代码了,而且我的观点一直是:设计模式,不仅让代码质量提高,而且

  理解起来更容易的

   那它代理了谁呢?这个问题确实让我困惑了很长时间

 

 protected class EditorDelegate implements ActionListener, ItemListener, Serializable {

        /**  The value of this cell. */
        protected Object value;

       /**
        * Returns the value of this cell. 
        * @return the value of this cell
        */
        public Object getCellEditorValue() {
            return value;
        }

       /**
        * Sets the value of this cell. 
        * @param value the new value of this cell
        */
    	public void setValue(Object value) { 
	    this.value = value; 
	}

       /**
        * Returns true if <code>anEvent</code> is <b>not</b> a
        * <code>MouseEvent</code>.  Otherwise, it returns true
        * if the necessary number of clicks have occurred, and
        * returns false otherwise.
        *
        * @param   anEvent         the event
        * @return  true  if cell is ready for editing, false otherwise
        * @see #setClickCountToStart
        * @see #shouldSelectCell
        */
        public boolean isCellEditable(EventObject anEvent) {
	    if (anEvent instanceof MouseEvent) { 
		return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
	    }
	    return true;
	}
    	
       /**
        * Returns true to indicate that the editing cell may
        * be selected.
        *
        * @param   anEvent         the event
        * @return  true 
        * @see #isCellEditable
        */
        public boolean shouldSelectCell(EventObject anEvent) { 
            return true; 
        }

       /**
        * Returns true to indicate that editing has begun.
        *
        * @param anEvent          the event
        */
        public boolean startCellEditing(EventObject anEvent) {
	    return true;
	}

       /**
        * Stops editing and
        * returns true to indicate that editing has stopped.
        * This method calls <code>fireEditingStopped</code>.
        *
        * @return  true 
        */
        public boolean stopCellEditing() { 
	    fireEditingStopped(); 
	    return true;
	}

       /**
        * Cancels editing.  This method calls <code>fireEditingCanceled</code>.
        */
       public void cancelCellEditing() { 
	   fireEditingCanceled(); 
       }

       /**
        * When an action is performed, editing is ended.
        * @param e the action event
        * @see #stopCellEditing
        */
        public void actionPerformed(ActionEvent e) {
            DefaultCellEditor.this.stopCellEditing();
	}

       /**
        * When an item's state changes, editing is ended.
        * @param e the action event
        * @see #stopCellEditing
        */
        public void itemStateChanged(ItemEvent e) {
	    DefaultCellEditor.this.stopCellEditing();
	}
    }

     里面实现的接口都是一般的公共的接口,至少不是那种玩具代码一样,一看就看出了代理谁了?

     返回前面看,我最初的想法是代理的是JTextField这种可以编辑的组件,这也好像瞒合理的,编辑器嘛,就是那些可以让你可以编辑的组件!

     

 public Component getTableCellEditorComponent(JTable table, Object value,
						 boolean isSelected,
						 int row, int column) {
        delegate.setValue(value);
	return editorComponent;
    }

    观察这个方法,可以很快的否定上面的假设.代理对象在这里并没有真正的去代理可编辑的组件

   这个时候让我犯难了,在前后看看AbstractCellEditor,实在想不出端倪!

 

  

 /**
     * The delegate class which handles all methods sent from the
     * <code>CellEditor</code>.
     */

 

   突然间看到了这句话,它很快的告诉了delegate的意图,原来代理对象是处理cellEdtor的一些接口!

  

 总结:

    没有对象思维方式,去探寻基于像java这种面向对象语言,尤其是其源代码,会让你觉得无路可走!

    其实解决这个问题的方式,应该先去弄明白CellEditor这样的接口,看里面封装了些什么行为!

   问题的最终解决是,复写一些CellEditor里面的行为,就可以很快的实现了

  

 /**
        * Returns true if <code>anEvent</code> is <b>not</b> a
        * <code>MouseEvent</code>.  Otherwise, it returns true
        * if the necessary number of clicks have occurred, and
        * returns false otherwise.
        *
        * @param   anEvent         the event
        * @return  true  if cell is ready for editing, false otherwise
        * @see #setClickCountToStart
        * @see #shouldSelectCell
        */
        public boolean isCellEditable(EventObject anEvent) {
	    if (anEvent instanceof MouseEvent) { 
		return ((MouseEvent)anEvent).getClickCount() >= clickCountToStart;
	    }
	    return true;
	}

 

或者直接把上面的代码拷过去,就ok了!

 

由解决问题方法想到的,自己在面向对象方面,尤其是思维层次上,还是一个弱项!

你可能感兴趣的:(设计模式,编程,Google)