问题背景:
项目中要实现自己的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了!
由解决问题方法想到的,自己在面向对象方面,尤其是思维层次上,还是一个弱项!