Domanda

Sto cercando di creare una tabella che funzioni come Excel. Ciò significa che quando un utente inizia a inserire dati nelle celle, il contenuto in esse viene selezionato e modificato dai nuovi dati inseriti.

È stato utile?

Soluzione

Puoi creare un TableCellEditor personalizzato per la tua tabella. Questa classe avrà una variabile di istanza di TextField , chiamiamola textField . Quindi il metodo getTableCellEditorComponent potrebbe apparire così:

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

Altri suggerimenti

La creazione di un editor personalizzato funziona correttamente se nella tabella sono presenti solo dati String e è necessario un solo editor. Tuttavia, se disponi di più tipi diversi di dati, come String, Integer, Double, valute, percentuali ecc. Che utilizzano tutti un JTextField come editor, devi creare più editor personalizzati.

Puoi leggere la Tabella Seleziona tutto Editor per un'altra possibile soluzione.

Nota che esiste anche un'altra possibilità, puoi ignorare JTable # preparEditor come il seguente:

@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 soluzione sopra non funziona quando si avvia la modifica con un clic del mouse.

Per alcune persone la soluzione è quella di chiamare selectAll () in un invokeLater () in modo che il testo venga selezionato dopo che gli eventi del mouse sono stati inviati, ma questo non funziona per me (probabilmente perché sto usando l'aspetto della sostanza e senti?)

Gli interni Swing ottengono in seguito un evento mouseReleased () e cambiano di nuovo il cursore, come mostrato in questa traccia dello stack:

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)

Ecco la mia soluzione: Ascolta le modifiche alla posizione del cursore e la prima volta che la selezione passa da tutto selezionato a nessuno selezionato dopo l'avvio della modifica della cella, chiama di nuovo selectAll (). Il listener di punti di inserimento può essere installato da un editor di celle personalizzato come mostrato qui o in un metodo editCellAt () sovrascritto in una JTable personalizzata.

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

Se il tuo obiettivo è quello di svuotare la cella all'avvio della modifica, non è necessario utilizzare selectAll () . Basta impostare il valore su null .

Esempio di implementazione:

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

Dovresti guardare extJS. C'è una curva di apprendimento piuttosto ripida, però ...

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top