質問

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

他のヒント

テーブルに文字列データのみがあり、単一のエディターのみが必要な場合、カスタムエディターの作成は正常に機能します。ただし、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()を呼び出して、マウスイベントがディスパッチされた後にテキストが選択されるようにすることですが、これは私にとっては機能していません(おそらく物質ルックを使用しているため)感じますか?)

このスタックトレースに示すように、スイング内部は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