how do I simulate “onStartCellEditing” for DefaultCellEditor

佐手、 提交于 2019-12-04 05:07:13

问题


CellEditorListener has "editingStopped" and "editingCancelled". But how might I implement a piece of code which needs to run when a cell editing session starts?

A typical example might be where you want the text of a JTextField editor component to go selectAll() when you start editing. I'm tempted to think the thing to do is override one of the methods of DefaultCellEditor, such as getTableCellEditorComponent or getCellEditorValue or getComponent, but none of these explicitly says they are called at the start of an edit session.

Conversely, we do know that JTable.getCellEditor returns the editor if we are editing, but null if not. This is because the component is made into a child object of JTable when editing starts. It also seems to get the focus at the beginning of an editing session, so you might perhaps think of add a FocusListener to the editor component (JTextField, etc.). But is this guaranteed? Also, maybe focus can be lost and then return during an editing session.

There's a way of listening for the "addition" (as a child object) of this editor component: ContainerListener. Unless someone tells me different this appears to be the most direct and rational way of getting a call that an editing session has begun. But it seems odd that there isn't a more direct way...


回答1:


A typical example might be where you want the text of a JTextField editor component to go selectAll() when you start editing.

You can override the editCellAt(...) method of JTable to select the text once editing has started:

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



回答2:


Rob Camick's answer is great, but I have another one for "completists" to peruse.

I use Jython but it should be simple enough for Java people to understand. In Python/Jython you can add arbitrary "attributes" to (almost) any object. So in editCellAt I add an attribute "start_editing" which then signals to the caret listener added to the JTextField editor component that a session has just begun. If the caret dot and mark are equal (collapsed), if the click-count-to-start-editing == 2, and if the editor has the "start_editing" attr, you select-all (again), and you also remove the "start_editing" attr... it works (!), without spawning a new 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 )

A similar result could be achieved in Java, clearly, using a private field of the editor, or something along those lines.

NB why have I put "requestFocus" in there? If you press key F2 on an editable table cell the editing starts and the editor component (typically a JTextField) gets focus automatically. However you can also start editing just by typing into the table cell. It took me much head-scratching to work out that, oddly, if you do this you do indeed start editing, but the editor component does not get focus automatically. So this is a way to "resolve this anomaly".

NB2 One final point about my solution. In a real-world implementation you also need to set a timer to remove the attribute "start_editing" after a certain finite time (e.g. 0.5 s). Otherwise you might click once, which would not start an editing session (if click-to-start == 2), and then click again 10 seconds later, after having started editing by another means, to find that selectAll happens confusingly and inexplicably. This attribute must be made to be like the tape in Mission Impossible: self-destruct after x seconds...



来源:https://stackoverflow.com/questions/33067595/how-do-i-simulate-onstartcellediting-for-defaultcelleditor

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!