Pregunta

Estoy tratando de hacer una tabla que funcione como Excel. Es decir, cuando un usuario comienza a insertar datos en las celdas, el contenido se selecciona y cambia por los nuevos datos insertados.

¿Fue útil?

Solución

Puedes crear un TableCellEditor personalizado para tu tabla. Esta clase tendrá una variable de instancia de un TextField , llamémosla textField . Entonces el método getTableCellEditorComponent podría tener este aspecto:

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

Otros consejos

La creación de un editor personalizado funciona bien si solo tiene datos de cadena en la tabla y solo necesita un único editor. Sin embargo, si tiene varios tipos diferentes de datos, como Cadena, Integer, Doble, monedas, porcentajes, etc., todos los cuales usan un JTextField como editor, entonces necesita crear varios editores personalizados.

Puede leer en Tabla Seleccionar todo Editor para otra posible solución.

Tenga en cuenta que también hay otra posibilidad, puede anular JTable # prepareEditor como la siguiente:

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

La solución anterior no funciona cuando la edición se inicia con un clic del mouse.

Para algunas personas, la solución es llamar a selectAll () en un invokeLater () para que el texto se seleccione después de que se hayan enviado los eventos del mouse, pero esto no funciona para mí (posiblemente porque estoy usando el aspecto de Sustancia y sentir?)

Las partes internas de Swing obtienen un evento mouseReleased () más tarde y cambian el cursor de nuevo, como se muestra en este seguimiento de pila:

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)

Aquí está mi solución: Escuche los cambios en la posición del cursor, y la primera vez que la selección pase de todos los seleccionados a ninguno seleccionado después de que haya comenzado la edición de celdas, llame a selectAll () nuevamente. El editor de celdas personalizadas puede instalar el detector de caretas como se muestra aquí, o en un método de edición de celda () anulado en una tabla JT personalizada.

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

Si su objetivo es vaciar la celda cuando comience la edición, no necesita utilizar selectAll () . Simplemente establezca el valor en null .

Ejemplo de implementación:

(anulando getTableCellEditorComponent () en 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;
    }
};

Deberías mirar extJS. Sin embargo, hay una curva de aprendizaje bastante empinada ...

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top