Select all data when start editing JTable Cell

2019-05-21 03:09发布

I'm trying to make a table that works like Excel. Meaning, when a user starts to insert data into the cells the content into them is selected and changed by the new data inserted.

6条回答
beautiful°
2楼-- · 2019-05-21 03:37

Note that there is also another possibility, you can override JTable#prepareEditor like the following:

@Override
public Component prepareEditor(TableCellEditor editor, int row, int column) {
    Component c = super.prepareEditor(editor, row, column);
    if (c instanceof JTextComponent) {
        ((JTextComponent) c).selectAll();
    } 
    return c;
}
查看更多
姐就是有狂的资本
3楼-- · 2019-05-21 03:40

Creating a custom editor works fine if you only ever have String data in the table and only need a single editor. However, if you have multiple different types of data, like String, Integer, Double, currencies, percentages etc which all use a JTextField as an editor then you need to create multiple custom editors.

You can read up on the Table Select All Editor for another possible solution.

查看更多
家丑人穷心不美
4楼-- · 2019-05-21 03:41

You should look at extJS. There is a pretty steep learning curve, though..

查看更多
何必那么认真
5楼-- · 2019-05-21 03:42

If your objective is to empty the cell when editing begins, no need to use selectAll(). Simply set value to null.

Implementation example:

(overriding getTableCellEditorComponent() in DefaultCellEditor)

TableCellEditor myCellEditor = new DefaultCellEditor(new JTextField()){
    @Override
    public Component getTableCellEditorComponent(JTable table, Object value,
                boolean isSelected, int row, int column)
    {
        // empty the cell on edit start
        delegate.setValue( (editorComponent instanceof JTextField)? null : value);
        return editorComponent;
    }
};
查看更多
Explosion°爆炸
6楼-- · 2019-05-21 03:43

The solution above doesn't work when editing is started by a mouse click.

For some people the solution is to call selectAll() in an invokeLater() so that the text gets selected after the mouse events have been dispatched, but this isn't working for me (possibly because I'm using Substance look and feel?)

Swing internals get a mouseReleased() event later and change the caret again, as shown in this stack trace:

at javax.swing.text.JTextComponent.fireCaretUpdate(Unknown Source)
at javax.swing.text.JTextComponent$MutableCaretEvent.fire(Unknown Source)
at javax.swing.text.JTextComponent$MutableCaretEvent.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.AWTEventMulticaster.mouseReleased(Unknown Source)
at java.awt.Component.processMouseEvent(Unknown Source)
at javax.swing.JComponent.processMouseEvent(Unknown Source)
at java.awt.Component.processEvent(Unknown Source)
at java.awt.Container.processEvent(Unknown Source)
at java.awt.Component.dispatchEventImpl(Unknown Source)
at java.awt.Container.dispatchEventImpl(Unknown Source)
at java.awt.Component.dispatchEvent(Unknown Source)
at javax.swing.plaf.basic.BasicTableUI$Handler.repostEvent(Unknown Source)

Here is my solution: Listen for caret position changes, and the first time the selection goes from all selected to none selected after cell editing has started, call selectAll() again. The caret listener can be installed by a custom cell editor as shown here, or in an overridden editCellAt() method in a custom JTable.

private class SelectAllCellEditor extends DefaultCellEditor
{
    public SelectAllCellEditor( JTextField tf )
    {
        super( tf );
    }

    /**
     * Flag to ensure we only install the caret listener on the editor once.
     */
    boolean listenerInstalled   = false;
    /**
     * Primes the caret listener to override deselection when the first mouseReleased() event is reposted to the editor.
     */
    boolean overrideDeselection = false;

    @Override
    public Component getTableCellEditorComponent( JTable table , Object value , boolean isSelected , int row , int column )
    {
        final JFormattedTextField tf = ( JFormattedTextField ) super.getTableCellEditorComponent( table , value , isSelected , row , column );

        if( !listenerInstalled )
        {
            tf.addCaretListener( new CaretListener( )
            {
                int lastDot     = 0;
                int lastMark    = 0;

                @Override
                public void caretUpdate( CaretEvent e )
                {
                    if( overrideDeselection )
                    {
                        int length = tf.getText( ) == null ? 0 : tf.getText( ).length( );

                        boolean wasAllSelected = ( lastDot == 0 && lastMark == length ) || ( lastDot == length && lastMark == 0 );
                        boolean nowNoneSelected = ( e.getDot( ) == 0 && e.getMark( ) == 0 ) || ( e.getDot( ) == length && e.getMark( ) == length );

                        if( wasAllSelected )
                        {
                            // don't try to override again until the next time cell editing is started
                            overrideDeselection = false;

                            // only re-select all if the selection went to none; otherwise the user clicked the cell and dragged to select part of the text
                            if( nowNoneSelected )
                            {
                                tf.selectAll( );
                            }
                        }
                    }

                    lastDot = e.getDot( );
                    lastMark = e.getMark( );
                }
            } );
            listenerInstalled = true;
        }

        // Prime the caret listener to override deselection when the first mouseReleased() event is reposted to the editor.
        overrideDeselection = true;
        tf.selectAll( );
        return tf;
    }
}
查看更多
别忘想泡老子
7楼-- · 2019-05-21 03:52

You can create a custom TableCellEditor for your table. This class will have an instance variable of a TextField, lets call it textField. Then the getTableCellEditorComponent method could look like this:

public Component getTableCellEditorComponent(JTable table, Object value, 
                             boolean isSelected, int row, int column ) {
    textField.setText(value.toString());
    textField.selectAll();
    return textField;
}
查看更多
登录 后发表回答