2

我正在尝试制作一个像 Excel 一样工作的表格。意思是,当用户开始将数据插入单元格时,插入的新数据会选择并更改其中的内容。

4

6 回答 6

3

您可以为您的表格创建一个自定义 TableCellEditor。这个类将有一个实例变量 a TextField,让我们调用它textField。然后该getTableCellEditorComponent方法可能如下所示:

public Component getTableCellEditorComponent(JTable table, Object value, 
                             boolean isSelected, int row, int column ) {
    textField.setText(value.toString());
    textField.selectAll();
    return textField;
}
于 2009-09-11T17:40:03.447 回答
2

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

您可以阅读表全选编辑器以获取另一种可能的解决方案。

于 2009-09-11T20:44:02.270 回答
2

请注意,还有另一种可能性,您可以覆盖 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;
}
于 2010-01-27T12:58:30.357 回答
0

通过鼠标单击开始编辑时,上述解决方案不起作用。

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

Swing 内部稍后会收到一个 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;
    }
}
于 2012-11-13T17:09:59.650 回答
0

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

实现示例:

(覆盖getTableCellEditorComponent()在 中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;
    }
};
于 2013-09-14T09:39:30.373 回答
-1

你应该看看 extJS。不过,学习曲线非常陡峭。

于 2009-09-11T17:30:54.440 回答