سؤال

ونحن نرى اختيار JTable الحصول على تطهيرها عندما نفعل fireTableDataChanged() أو fireTableRowsUpdated() من TableModel.

هل هذا هو متوقع، أو نفعل شيئا خاطئا؟ لم أكن أرى أي ممتلكات على JTable (أو الطبقات الأخرى ذات الصلة) حول مسح / الحفاظ على الاختيار على تحديثات النموذج.

وإذا كان هذا هو السلوك الافتراضي، ليس هناك وسيلة جيدة لمنع هذا؟ ربما بعض الطريق إلى "تأمين" اختيار قبل التحديث وفتح بعد؟

والمطور تم تجريب إنقاذ التحديد قبل التحديث وإعادة تطبيقه. انها بطيئة بعض الشيء.

وهذا هو جافا 1.4.2 على نظام التشغيل Windows XP، إذا ما يهم. نحن تقتصر على هذا الإصدار استنادا إلى بعض رمز بائع التي نستخدمها.

هل كانت مفيدة؟

المحلول

وتحتاج إلى الحفاظ على الاختيار وثم إعادة تطبيق ذلك.

وقبل كل شيء سوف تحتاج إلى الحصول على قائمة من كافة الخلايا المحددة.

وبعد ذلك عند إعادة تحميل JTable مع البيانات الجديدة تحتاج إلى برمجيا إعادة تطبيق تلك التحديدات نفسها.

والنقطة الأخرى اريد ان يكون هو، إذا كان عدد أو الصفوف أو الأعمدة في الجدول الخاص بك تتزايد أو تتناقص بعد كل تحديث نموذج الجدول، ثم الرجاء لا تهتم بالحفاظ على الاختيار.

ويمكن للمستخدم من اختيار الصف 2 عمود 1 وجود قيمة تقول "بطة"، قبل updation نموذج. ولكن بعد updation النموذج الذي نفس البيانات يمكن أن يحدث الآن في الصف 4 العمود 1، والصف خلية الأصلي 2 عمود 1 يمكن أن البيانات الجديدة مثل "خنزير". الآن إذا كنت قسرا تعيين التحديد إلى ما كانت عليه قبل updation نموذج، هذا قد لا يكون ما يريده المستخدم.

وهكذا الخلايا اختيار برمجيا يمكن أن يكون سلاح ذو حدين. لا تفعل ذلك، إذا لم تكن متأكدا.

نصائح أخرى

ويمكنك الحفاظ على اختيار الجدول تلقائيا إذا كان هيكل من هذا الجدول لم يتغير (أي إذا لم تكن إضافة / إزالة أي الأعمدة / الصفوف) على النحو التالي.

إذا كنت قد كتبت تنفيذ الخاص بك من TableModel، يمكنك ببساطة تجاوز أسلوب fireTableDataChanged ():

        @Override
        public void fireTableDataChanged() {
            fireTableChanged(new TableModelEvent(this, //tableModel
                                                 0, //firstRow
                                                 getRowCount() - 1, //lastRow 
                                                 TableModelEvent.ALL_COLUMNS, //column 
                                                 TableModelEvent.UPDATE)); //changeType
        }

وهذا ينبغي أن تكفل اختيارك الحفاظ شريطة أن البيانات فقط وليس تغير بنية الجدول. والفرق الوحيد بين هذا وما يمكن أن يسمى إذا لم يتم تجاوز هذا الأسلوب هو أن getRowCount () - 1 يتم تمرير الوسيطة lastRow بدلا من Integer.MAX_VALUE، وهذه الأخيرة التي يعمل الدال الذي لديه ليس فقط كل البيانات في الجدول يتغير إلا أن عدد الصفوف قد يكون كذلك.

وكان لي نفس المشكلة في التطبيق. في حالتي كان النموذج في الجدول قائمة الكائنات، حيث خصائص الكائن حيث تعيينها إلى الأعمدة. في هذه الحالة، عندما تم تعديل القائمة، I استرداد الفهرس المحدد وتخزين الكائن الذي تم تحديده قبل تحديث قائمة. بعد قائمة معدلة وقبل أن يتم تحديث الجدول، وأود أن حساب موضع الكائن المحدد. إذا كان لا يزال موجودا بعد التعديل، ثم أود أن تعيين التحديد إلى المؤشر الجديد.

ومجرد وضع الفهرس المحدد في الجدول بعد ان التعديل لا تعمل، لأن الكائن قد تغير الموقف في القائمة.

وكملاحظة جانبية، وجدت أن العمل مع GlazedLists يجعل الحياة أسهل بكثير عند التعامل مع الجداول.

وهذا هو السلوك الافتراضي. إذا كنت استدعاء fireTableDataChanged() الجدول بأكمله هو إعادة بناء من نقطة الصفر كما قمت بتعيين نموذج جديد تماما. في هذه الحالة اختيار هو، بطبيعة الحال، فقدت. إذا كنت استدعاء fireTableRowsUpdated() أخلى اختيار أيضا في الحالات العامة. الطريقة الوحيدة هي أن نتذكر اختيار ثم قم بتعيين هذا. للأسف ليس هناك ما يضمن أن اختيار ستظل سارية المفعول. كن حذرا إذا استعادة الاختيار.

ولتكون مرجعا، كما جاءSwapnonil موخرجي، وهذا لا حيلة مع جدول مع صفوف اختيار:

        // preserve selection calling fireTableDataChanged()
        final int[] sel = table.getSelectedRows();

        fireTableDataChanged();

        for (int i=0; i<sel.length; i++)
            table.getSelectionModel().addSelectionInterval(sel[i], sel[i]);

إذا لم تخني، وتوفير الاختيار وإعادة تطبيقه هو ما قمنا به جدا ...

وكنت أواجه نفس القضية، وعندما حاول البحث في السبب في أنني حصلت على هذا السؤال ولكن على ما يبدو خطأ في جافا SDK. http://bugs.sun.com/bugdatabase/view_bug.do؟bug_id=4276786

وتغلب على

وهناك عمل حول مؤقت هو متاح. يجب إزالته بمجرد إصلاح هذا الخطأ كما انها لم تختبر مدى ملاءمتها ضد الإصدارات الثابت.

استخدم هذا فرعية من JTable.

ملحوظة: هذا هو لMetalLookAndFeel. إذا كنت تستخدم نظرة الآخرين، ويشعر، فإن FixedTableUI فرعية داخلية لديها لتوسيع فئة فرعية TableUI لهذا الشكل والمظهر.

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.table.*;
import javax.swing.event.*;
import javax.swing.plaf.basic.*;

public class FixedTable extends JTable {

  private boolean isControlDownInDrag;

  public FixedTable(TableModel model) {
      super(model);
      setUI(new FixedTableUI());
  }

  private class FixedTableUI extends BasicTableUI {
      private MouseInputHandler handler = new MouseInputHandler() {
          public void mouseDragged(MouseEvent e) {
              if (e.isControlDown()) {
                  isControlDownInDrag = true;
              }
              super.mouseDragged(e);
          }

          public void mousePressed(MouseEvent e) {
              isControlDownInDrag = false;
              super.mousePressed(e);
          }

          public void mouseReleased(MouseEvent e) {
              isControlDownInDrag = false;
              super.mouseReleased(e);
          }
      };

      protected MouseInputListener createMouseInputListener() {
          return handler;
      }
  }

  public void changeSelection(int rowIndex, int columnIndex, boolean toggle, boolean extend) {
      if (isControlDownInDrag) {
          ListSelectionModel rsm = getSelectionModel();
          ListSelectionModel csm = getColumnModel().getSelectionModel();

          int anchorRow = rsm.getAnchorSelectionIndex();
          int anchorCol = csm.getAnchorSelectionIndex();

          boolean anchorSelected = isCellSelected(anchorRow, anchorCol);

          if (anchorSelected) {
              rsm.addSelectionInterval(anchorRow, rowIndex);
              csm.addSelectionInterval(anchorCol, columnIndex);
          } else {
              rsm.removeSelectionInterval(anchorRow, rowIndex);
              csm.removeSelectionInterval(anchorCol, columnIndex);
          }

          if (getAutoscrolls()) {
              Rectangle cellRect = getCellRect(rowIndex, columnIndex, false);
              if (cellRect != null) {
                  scrollRectToVisible(cellRect);
              }
          }
      } else {
          super.changeSelection(rowIndex, columnIndex, toggle, extend);
      }
  }
}

<قوية> ملاحظة http://bugs.sun.com

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