سؤال

أحاول صنع طاولة تعمل مثل 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 أو Integer أو Double و Currencies أو النسب المئوية وما إلى ذلك والتي تستخدم جميعها JTextfield كمحرر ، فأنت بحاجة إلى إنشاء محررين مخصصين متعددين.

يمكنك القراءة على جدول حدد كل المحرر لحل آخر ممكن.

لاحظ أن هناك أيضًا احتمالًا آخر ، يمكنك تجاوز Jtable#إعداد مثل ما يلي:

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

لا يعمل الحل أعلاه عند بدء التحرير بنقرة ماوس.

بالنسبة لبعض الأشخاص ، فإن الحل هو استدعاء Selectall () في Invokelater () بحيث يتم اختيار النص بعد إرسال أحداث الماوس ، لكن هذا لا يعمل بالنسبة لي (ربما لأنني أستخدم مظهرًا ومظهرًا للمواد؟ )

يحصل الأرجوحة الداخلية على حدث MousereleSESS () لاحقًا وقم بتغيير الكاريت مرة أخرى ، كما هو موضح في تتبع المكدس:

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)

هذا هو الحل:استمع إلى تغييرات في موقع Caret ، وفي المرة الأولى التي ينتقل فيها التحديد من كل شيء محدد إلى أي شيء تم تحديده بعد بدء تحرير الخلايا ، Call Selectall () مرة أخرى. يمكن تثبيت مستمع Caret بواسطة محرر خلية مخصصة كما هو موضح هنا ، أو بطريقة EditCellat () المتجاوز في JTable مخصصة.

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.

مثال التنفيذ:

(تجاوز getTableCellEditorComponent() في 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;
    }
};

يجب أن تنظر إلى extjs. هناك منحنى تعليمي شديد الانحدار ، رغم ذلك ..

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top