簡體   English   中英

開始編輯JTable單元時選擇所有數據

[英]Select all data when start editing JTable Cell

我正在嘗試制作一個類似於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;
}

如果表中只有String數據,並且只需要一個編輯器,那么創建自定義編輯器就可以很好地工作。 但是,如果您有多種不同類型的數據,例如字符串,整數,雙精度型,貨幣,百分比等,它們都使用JTextField作為編輯器,那么您需要創建多個自定義編輯器。

您可以在Table Select All Editor上閱讀,以獲得另一種可能的解決方案。

請注意,還有另一種可能性,您可以像下面這樣重寫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(),以便在調度鼠標事件后選擇文本,但這對我不起作用(可能是因為我使用的是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;
    }
}

如果您的目標是在開始編輯時清空單元格,則無需使用selectAll() 只需將value設置為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 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM