如何为DefaultCellEditor模拟“onStartCellEditing”

时间:2015-10-11 16:52:41

标签: java swing tablecelleditor

CellEditorListener具有“editingStopped”和“editingCancelled”。但是,我如何实现一个需要在单元格编辑会话开始时运行的代码?

一个典型示例可能是您希望在开始编辑时JTextField编辑器组件的文本转到selectAll()的位置。我很想要做的事情是覆盖DefaultCellEditor的一个方法,例如getTableCellEditorComponent或getCellEditorValue或getComponent,但是没有一个明确地说它们是在编辑会话开始时调用的。

相反,我们知道如果我们正在编辑JTable.getCellEditor会返回编辑器,否则返回null。这是因为在编辑开始时组件被制成JTable的子对象。它似乎也在编辑会话开始时得到了关注,因此您可能会想到将FocusListener添加到编辑器组件(JTextField等)。但这有保证吗?此外,可能会丢失焦点,然后在编辑会话期间返回。

有一种方法可以监听此编辑器组件的“添加”(作为子对象):ContainerListener。除非有人告诉我不同​​,否则这似乎是获得编辑会话已开始的电话的最直接和最合理的方式。但似乎很奇怪,没有更直接的方式...

2 个答案:

答案 0 :(得分:2)

  

一个典型的例子可能是您希望在开始编辑时JTextField编辑器组件的文本转到selectAll()。

您可以覆盖JTable的editCellAt(...)方法,以便在编辑开始后选择文本:

@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;
}

答案 1 :(得分:1)

罗布·卡米克的回答很棒,但我还有另一个回答#34; completists"仔细阅读。

我使用Jython但它应该足够简单,以便Java人员理解。在Python / Jython中,您可以添加任意"属性" (几乎)任何物体。所以在editCellAt中我添加了一个属性" start_editing"然后发信号给插入符号监听器添加到JTextField编辑器组件会话刚刚开始。如果插入点和标记相等(折叠),如果点击计数到开始编辑== 2,并且编辑器具有" start_editing" attr,你选择全部(再次),你也删除" start_editing" attr ...它可以工作(!),而不会产生新的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中实现类似的结果。

注意为什么我要把#34; requestFocus"在那里?如果在可编辑的表格单元格上按F2键,编辑将开始,编辑器组件(通常是JTextField)将自动获得焦点。但是,您也可以通过键入表格单元格来开始编辑。奇怪的是,如果你这样做,你确实开始编辑,但是 编辑器组件没有自动获得焦点 ,这让我感到很头疼。所以这是一种解决这种异常的方法"。

NB2关于我的解决方案的最后一点。在实际实现中,您还需要设置一个计时器来删除属性" start_editing"在一定的有限时间(例如0.5秒)之后。否则你可能会点击一次,这不会启动编辑会话(如果点击开始== 2),然后在10秒后再次点击,在通过其他方式开始编辑后,发现selectAll发生了令人困惑和莫名其妙的混乱。这个属性必须像“不可能的任务”中的磁带一样:x秒后自毁......