Frage

Wir sehen JTable Auswahl gelöscht werden, wenn wir einen fireTableDataChanged() oder fireTableRowsUpdated() vom TableModel tun.

Ist das erwartet, oder machen wir etwas falsch gemacht? Ich habe keine Eigenschaft auf der JTable (oder anderen verwandten Klassen) über Clearing / Erhaltung Auswahl an Modell-Updates.

Wenn das Standardverhalten, gibt es eine gute Möglichkeit, dies zu verhindern? Vielleicht nach irgendeiner Weise zu „sperren“ die Auswahl vor dem Update und entsperren?

Der Entwickler wurde das Experimentieren mit der Auswahl vor dem Update speichern und wieder ihre Anwendung. Es ist ein wenig langsam.

Dies ist Java 1.4.2 auf Windows XP, wenn es ankommt. Wir sind basierend auf einigen Lieferantencode auf diese Version beschränkt die wir verwenden.

War es hilfreich?

Lösung

Sie müssen die Auswahl zu erhalten und dann erneut bewerben.

Zunächst einmal müssen Sie eine Liste aller ausgewählten Zellen erhalten.

Wenn Sie dann erneut laden JTable mit den neuen Daten, die Sie programmatisch müssen die gleichen Auswahlen erneut anwenden.

Der andere Punkt, den ich machen will, ist, wenn die Anzahl oder Zeilen oder Spalten in der Tabelle steigen oder nach jedem Tischmodell Reload abnimmt, dann bitte nicht stört die Auswahl zu erhalten.

Der Benutzer Zeile 2 Spalte 1 könnte einen Wert sagen „Duck“ mit ausgewählt, bevor Modell updation. Aber nach Modell updation, dass dieselben Daten nun in Zeile 4 Spalte 1, und Ihre ursprüngliche Zellenzeile 2 Spalte 1 könnten neue Daten wie „Schwein“ auftreten können. Nun, wenn Sie mit Gewalt die Auswahl bestätigen, was es war, bevor das Modell updation, kann dies nicht sein, was die Nutzer wollten.

So programmatisch Auswahl von Zellen könnten ein zweischneidiges Schwert sein. Tun Sie es nicht, wenn Sie nicht sicher sind.

Andere Tipps

Sie können automatisch einer Tabelle Auswahl erhalten, wenn die Struktur der Tabelle nicht geändert hat (das heißt, wenn Sie nicht haben, hinzufügen / entfernen alle Spalten / Zeilen) wie folgt.

Wenn Sie eine eigene Implementierung von Tablemodel geschrieben haben, können Sie einfach überschreiben die fireTableDataChanged () Methode:

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

und dies sollte sicherstellen, dass Ihre Auswahl nur unter der Voraussetzung aufrechterhalten wird, dass die Daten und nicht die Struktur der Tabelle geändert hat. Der einzige Unterschied zwischen diesem und was passiert, wenn diese Methode nicht überschrieben genannt würde wurden, ist, dass getRowCount () - 1 für das LastRow Argument übergeben wird statt Integer.MAX_VALUE, von denen die letztere wirkt ein Signifikant, die nicht nur hat die ganze Daten in der Tabelle geändert, aber dass die Anzahl der Zeilen als auch.

Ich hatte das gleiche Problem in einer Anwendung. In meinem Fall war das Modell in der Tabelle eine Liste von Objekten, wo die Objekteigenschaften, wo Spalten abgebildet. In diesem Fall, wenn die Liste geändert wurde, abgerufen ich den ausgewählten Index und das Objekt gespeichert, die vor der Aktualisierung der Liste ausgewählt wurde. Nachdem die Liste geändert wird, und bevor die Tabelle aktualisiert wird, würde ich die Position des ausgewählten Objekts berechnen. Wenn es noch nach der Änderung ist, dann würde ich die Auswahl auf den neuen Index gesetzt.

Sie einfach den ausgewählten Index in der Tabelle Einstellung nach der Änderung wird nicht funktionieren, weil die Objektposition in der Liste ändern kann.

Als Randbemerkung, fand ich, dass mit GlazedLists Arbeit macht das Leben viel einfacher, wenn mit Tabellen zu tun.

Dies ist das Standardverhalten. Wenn Sie fireTableDataChanged() die gesamte Tabelle nennen, ist von Grund auf neu erstellen, wie Sie ganz neues Modell gesetzt. In diesem Fall ist die Auswahl natürlich verloren. Wenn Sie fireTableRowsUpdated() die Auswahl nennen ist auch in allgemeinen Fällen gelöscht. Die einzige Möglichkeit ist die Auswahl zu erinnern und diese dann festgelegt. Leider gibt es keine Garantie, dass die Auswahl immer noch gültig ist. Seien Sie vorsichtig, wenn die Wiederherstellung Auswahl.

als Referenz, wie @Swapnonil Mukherjee erklärte, tat dies den Trick mit einem Tisch mit wählbaren Zeilen:

        // 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]);

Wenn ich mich richtig erinnere, Speichern Auswahl und Wieder Anwendung ist es, was wir auch getan haben ...

Ich war mit Blick auf gleiches Problem und wenn versucht, den Grund, warum ich diese Frage bekam zu suchen, aber es scheint einen Fehler in Java SDK. http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4276786

Umgehen

Eine vorübergehende Behelfslösung ist verfügbar. Es sollte entfernt werden, sobald dieser Fehler behoben wird, wie es Eignung ist hat nicht gegen feste Versionen getestet.

Mit dieser Unterklasse von JTable.

Hinweis: Dies ist für die MetalLookAndFeel. Wenn andere Blick mit und fühlt, wird die innere FixedTableUI Unterklasse der TableUI Unterklasse für diesen Blick erweitern müssen und fühlen.

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

Hinweis Curtsey http://bugs.sun.com

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top