如何为 DefaultCellEditor 模拟 "onStartCellEditing"
how do I simulate "onStartCellEditing" for DefaultCellEditor
CellEditorListener 有 "editingStopped" 和 "editingCancelled"。但是,当单元格编辑会话开始时,我该如何实现一段需要 运行 的代码?
一个典型的例子可能是当您开始编辑时,您希望 JTextField 编辑器组件的文本转到 selectAll()。我很想认为要做的事情是重写 DefaultCellEditor 的一种方法,例如 getTableCellEditorComponent 或 getCellEditorValue 或 getComponent,但其中 none 明确表示它们在编辑会话开始时被调用。
相反,如果我们正在编辑,我们确实知道 JTable.getCellEditor return 是编辑器,但如果不是,则为 null。这是因为在编辑开始时组件被做成了JTable 的子对象。它还似乎在编辑会话开始时获得焦点,因此您可能会考虑将 FocusListener 添加到编辑器组件(JTextField 等)。但这有保证吗?此外,在编辑会话期间可能会失去焦点,然后 return。
有一种侦听此编辑器组件的 "addition"(作为子对象)的方法:ContainerListener。除非有人告诉我不同的说法,否则这似乎是接到电话通知编辑会话已经开始的最直接、最合理的方式。但是没有更直接的方法似乎很奇怪...
A typical example might be where you want the text of a JTextField editor component to go selectAll() when you start editing.
编辑开始后,您可以将 JTable 的 editCellAt(...)
方法重写为 select 文本:
@Override
public boolean editCellAt(int row, int column, EventObject e)
{
boolean result = super.editCellAt(row, column, e);
final Component editor = getEditorComponent();
if (editor != null && editor instanceof JTextComponent)
{
((JTextComponent)editor).selectAll();
if (e == null)
{
((JTextComponent)editor).selectAll();
}
else if (e instanceof MouseEvent)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
((JTextComponent)editor).selectAll();
}
});
}
}
return result;
}
Rob Camick 的回答很好,但我还有另一个答案供 "completists" 细读。
我使用 Jython,但它应该足够简单以供 Java 人理解。在 Python/Jython 中,您可以向(几乎)任何对象添加任意 "attributes"。因此,在 editCellAt 中,我添加了一个属性 "start_editing",然后向添加到 JTextField 编辑器组件的插入符号侦听器发出会话刚刚开始的信号。如果插入点和标记相等(折叠),如果开始编辑的点击计数 == 2,并且如果编辑器具有 "start_editing" 属性,则您 select-all(再次),并且您还删除了 "start_editing" 属性...它可以工作(!),而无需生成新的 Runnable。
class DatesTable( javax.swing.JTable ):
def editCellAt(self, row, column, event_obj ):
result = self.super__editCellAt( row, column, event_obj )
if self.editorComponent:
self.editorComponent.requestFocus() # explanation below
self.editorComponent.selectAll()
if isinstance( event_obj, java.awt.event.MouseEvent ):
self.cellEditor.start_editing = None
return result
class DatesTableCellEditor( javax.swing.DefaultCellEditor ):
def __init__( editor_self, table, *args, **kvargs ):
jtf = javax.swing.JTextField()
class JTFCaretListener( javax.swing.event.CaretListener ):
def caretUpdate( self, caret_event ):
if hasattr( editor_self, 'start_editing' ):
del editor_self.start_editing
if caret_event.dot == caret_event.mark and editor_self.clickCountToStart == 2:
caret_event.source.selectAll()
jtf.addCaretListener( JTFCaretListener())
javax.swing.DefaultCellEditor.__init__( editor_self, jtf, **kvargs )
在 Java 中可以实现类似的结果,显然,使用编辑器的私有字段,或类似的东西。
注意为什么我把 "requestFocus" 放在那里?如果在 editable table 单元格上按 F2 键,编辑就会开始,编辑器组件(通常是 JTextField)会自动获得焦点。但是,您也可以通过在 table 单元格中键入内容来开始编辑。我费了好大劲才弄明白,奇怪的是,如果你这样做,你确实开始编辑了,但是 editor 组件不会自动获得焦点。所以这是 "resolve this anomaly".
的一种方式
NB2 关于我的解决方案的最后一点。在现实世界的实现中,您还需要设置一个计时器,以便在一定的有限时间(例如 0.5 秒)后删除属性 "start_editing"。否则您可能会单击一次,这不会启动编辑会话(如果单击开始 == 2),然后在 10 秒后再次单击,在通过另一种方式开始编辑后,会发现 selectAll发生混乱和莫名其妙。此属性必须像碟中谍中的磁带一样:x 秒后自毁...
CellEditorListener 有 "editingStopped" 和 "editingCancelled"。但是,当单元格编辑会话开始时,我该如何实现一段需要 运行 的代码?
一个典型的例子可能是当您开始编辑时,您希望 JTextField 编辑器组件的文本转到 selectAll()。我很想认为要做的事情是重写 DefaultCellEditor 的一种方法,例如 getTableCellEditorComponent 或 getCellEditorValue 或 getComponent,但其中 none 明确表示它们在编辑会话开始时被调用。
相反,如果我们正在编辑,我们确实知道 JTable.getCellEditor return 是编辑器,但如果不是,则为 null。这是因为在编辑开始时组件被做成了JTable 的子对象。它还似乎在编辑会话开始时获得焦点,因此您可能会考虑将 FocusListener 添加到编辑器组件(JTextField 等)。但这有保证吗?此外,在编辑会话期间可能会失去焦点,然后 return。
有一种侦听此编辑器组件的 "addition"(作为子对象)的方法:ContainerListener。除非有人告诉我不同的说法,否则这似乎是接到电话通知编辑会话已经开始的最直接、最合理的方式。但是没有更直接的方法似乎很奇怪...
A typical example might be where you want the text of a JTextField editor component to go selectAll() when you start editing.
编辑开始后,您可以将 JTable 的 editCellAt(...)
方法重写为 select 文本:
@Override
public boolean editCellAt(int row, int column, EventObject e)
{
boolean result = super.editCellAt(row, column, e);
final Component editor = getEditorComponent();
if (editor != null && editor instanceof JTextComponent)
{
((JTextComponent)editor).selectAll();
if (e == null)
{
((JTextComponent)editor).selectAll();
}
else if (e instanceof MouseEvent)
{
SwingUtilities.invokeLater(new Runnable()
{
public void run()
{
((JTextComponent)editor).selectAll();
}
});
}
}
return result;
}
Rob Camick 的回答很好,但我还有另一个答案供 "completists" 细读。
我使用 Jython,但它应该足够简单以供 Java 人理解。在 Python/Jython 中,您可以向(几乎)任何对象添加任意 "attributes"。因此,在 editCellAt 中,我添加了一个属性 "start_editing",然后向添加到 JTextField 编辑器组件的插入符号侦听器发出会话刚刚开始的信号。如果插入点和标记相等(折叠),如果开始编辑的点击计数 == 2,并且如果编辑器具有 "start_editing" 属性,则您 select-all(再次),并且您还删除了 "start_editing" 属性...它可以工作(!),而无需生成新的 Runnable。
class DatesTable( javax.swing.JTable ):
def editCellAt(self, row, column, event_obj ):
result = self.super__editCellAt( row, column, event_obj )
if self.editorComponent:
self.editorComponent.requestFocus() # explanation below
self.editorComponent.selectAll()
if isinstance( event_obj, java.awt.event.MouseEvent ):
self.cellEditor.start_editing = None
return result
class DatesTableCellEditor( javax.swing.DefaultCellEditor ):
def __init__( editor_self, table, *args, **kvargs ):
jtf = javax.swing.JTextField()
class JTFCaretListener( javax.swing.event.CaretListener ):
def caretUpdate( self, caret_event ):
if hasattr( editor_self, 'start_editing' ):
del editor_self.start_editing
if caret_event.dot == caret_event.mark and editor_self.clickCountToStart == 2:
caret_event.source.selectAll()
jtf.addCaretListener( JTFCaretListener())
javax.swing.DefaultCellEditor.__init__( editor_self, jtf, **kvargs )
在 Java 中可以实现类似的结果,显然,使用编辑器的私有字段,或类似的东西。
注意为什么我把 "requestFocus" 放在那里?如果在 editable table 单元格上按 F2 键,编辑就会开始,编辑器组件(通常是 JTextField)会自动获得焦点。但是,您也可以通过在 table 单元格中键入内容来开始编辑。我费了好大劲才弄明白,奇怪的是,如果你这样做,你确实开始编辑了,但是 editor 组件不会自动获得焦点。所以这是 "resolve this anomaly".
的一种方式NB2 关于我的解决方案的最后一点。在现实世界的实现中,您还需要设置一个计时器,以便在一定的有限时间(例如 0.5 秒)后删除属性 "start_editing"。否则您可能会单击一次,这不会启动编辑会话(如果单击开始 == 2),然后在 10 秒后再次单击,在通过另一种方式开始编辑后,会发现 selectAll发生混乱和莫名其妙。此属性必须像碟中谍中的磁带一样:x 秒后自毁...