Question

J'essaie de créer un tableau qui fonctionne comme Excel. Cela signifie que lorsqu'un utilisateur commence à insérer des données dans les cellules, le contenu qu'elles contiennent est sélectionné et modifié par les nouvelles données insérées.

Était-ce utile?

La solution

Vous pouvez créer un TableCellEditor personnalisé pour votre table. Cette classe aura une variable d'instance d'un TextField , appelons-la textField . La méthode getTableCellEditorComponent pourrait alors ressembler à ceci:

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

Autres conseils

La création d'un éditeur personnalisé fonctionne correctement si vous ne disposez que de données String dans la table et si vous n'avez besoin que d'un seul éditeur. Toutefois, si vous avez plusieurs types de données différents, tels que String, Integer, Double, devises, pourcentages, etc., qui utilisent tous un JTextField en tant qu'éditeur, vous devez créer plusieurs éditeurs personnalisés.

Vous pouvez consulter le éditeur de tableau pour une autre solution possible.

Notez qu'il existe également une autre possibilité, vous pouvez remplacer JTable # prepareEditor comme suit:

@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 solution ci-dessus ne fonctionne pas lorsque l'édition est démarrée par un clic de souris.

Pour certaines personnes, la solution consiste à appeler selectAll () dans invokeLater () afin que le texte soit sélectionné après la distribution des événements de souris, mais cela ne fonctionne pas pour moi (probablement parce que j'utilise Substance Look. et se sentir?)

Les internes de Swing obtiennent un événement mouseReleased () plus tard et modifient à nouveau le curseur, comme indiqué dans cette trace de pile:

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)

Voici ma solution: Écoutez les modifications de la position du curseur et la première fois que la sélection passe de toutes les sélections à aucune après le début de l'édition des cellules, appelez à nouveau selectAll (). L'écouteur d'insertion peut être installé à l'aide d'un éditeur de cellule personnalisé, comme indiqué ici, ou d'une méthode editCellAt () remplacée dans une table JTable personnalisée.

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 votre objectif est de vider la cellule au début de l'édition, inutile d'utiliser selectAll () . Définissez simplement la valeur sur null .

Exemple d'implémentation:

(remplacement de getTableCellEditorComponent () dans 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;
    }
};

Vous devriez regarder extJS. Il y a une courbe d'apprentissage assez raide, bien que ..

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top