我正在尝试创建一个像Excel一样的表。这意味着,当用户开始将数据插入单元格时,内容将被选中并由插入的新数据更改。

有帮助吗?

解决方案

您可以为表创建自定义TableCellEditor。该类将具有 TextField 的实例变量,我们将其称为 textField 。然后 getTableCellEditorComponent 方法可能如下所示:

public Component getTableCellEditorComponent(JTable table, Object value, 
                             boolean isSelected, int row, int column ) {
    textField.setText(value.toString());
    textField.selectAll();
    return textField;
}

其他提示

如果表中只有String数据并且只需要一个编辑器,那么创建自定义编辑器就可以正常工作。但是,如果您有多种不同类型的数据,如String,Integer,Double,currency,percentages等,它们都使用JTextField作为编辑器,那么您需要创建多个自定义编辑器。

您可以阅读表格选择所有编辑器为另一种可能的解决方案。

请注意,还有另一种可能性,您可以覆盖JTable#prepareEditor,如下所示:

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

通过鼠标单击启动编辑时,上述解决方案无效。

对于某些人来说,解决方法是在invokeLater()中调用selectAll(),以便在调度鼠标事件后选择文本,但这对我不起作用(可能是因为我正在使用Substance look感觉?)

Swing internals稍后获取mouseReleased()事件并再次更改插入符号,如此堆栈跟踪所示:

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)

以下是我的解决方案: 监听插入符号位置更改,并且在单元格编辑开始后第一次从所有选定选择到无选择时,再次调用selectAll()。插入符听众可以通过自定义单元格编辑器安装,如此处所示,也可以在自定义JTable中的重写editCellAt()方法中安装。

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

如果您的目标是在编辑开始时清空单元格,则无需使用 selectAll()。只需将值设置为 null

实施示例:

(覆盖 DefaultCellEditor 中的 getTableCellEditorComponent()

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

你应该看看extJS。虽然有一个非常陡峭的学习曲线。

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top