2016-04-15 10 views
0

Es ist schwierig zu erklären, ich werde es versuchen und es in Schritten erklären, Code nebeneinander zu laufen wird helfen, aber das Betrachten von Bildern sollte ausreichen, um meine Frage zu verstehen.Interessantes Verhalten von Zeile, Modellreihe und Ansichtszeile - welche zu verwenden wann?

row und rowModel sind konsistent mit Datenanzeige und Datenmodell, aber ich kann rowView überhaupt nicht verstehen. Wann wird rowView nützlich sein?

1) Standardansicht: Spalte B (1,2,3,4).

enter image description here

2) Klicken Sie auf Spalte B-Header zu sortieren: aufsteigend sortieren (1,2,3,4). Immer dataRow = modelRow = viewRow.

3) Klicken Sie, um die Überschrift der Spalte B zu sortieren: Absteigend sortieren (4,3,2,1).

Zeile 0 = rowModel 3 = rowView 3

Reihe 1 = rowModel 2 = rowView 2

Zeile 2 = rowModel 1 = rowView 1

Zeile 3 = rowModel 0 = rowView 0

Alles wie erwartet!

4) Klicken Sie nun Spalte C sortieren: Sortierung aufsteigend (Abbildung unten)

enter image description here

Spalte 0: Wert "4" - Zeile 0 = rowModel 3 = rowView 2 --- warum rowView ist 2?

Spalte 1: Wert "1" - Zeile 0 = ZeileModell 3 = ZeileView 2 --- Warum RowView ist 2 und konsistent Verhalten in verbleibenden Zellen wie unten?

Spalte 0: Wert "3" - Zeile 1 = ZeileModell 2 = ZeileView 3 --- Warum RowView ist 3?

Spalte 1: Wert "3" - Zeile 1 = ZeileModell 2 = ZeileView 3 --- Warum RowView ist 3?

Spalte 0: Wert "1" - Zeile 2 = ZeileModell 0 = ZeileView 1 --- warum rowView ist 1?

Spalte 1: Wert "4" - Zeile 2 = ZeileModell 0 = ZeileView 1 --- warum rowView ist 1?

Spalte 0: Wert "2" - Zeile 3 = ZeileModell 1 = ZeileView 0 --- Warum RowView ist 0?

Spalte 1: Wert "5" - Zeile 3 = ZeileModell 1 = ZeileView 0 --- Warum rowView ist 0?

Code:

import javax.swing.*; 
import javax.swing.table.DefaultTableCellRenderer; 
import javax.swing.table.DefaultTableModel; 
import javax.swing.table.TableCellRenderer; 
import javax.swing.table.TableModel; 
import java.awt.*; 

public class SortTableWithColors_ extends JFrame { 
    public static void main(String[] args) { 
     SortTableWithColors_ frame = new SortTableWithColors_(); 
     frame.setDefaultCloseOperation(WindowConstants.EXIT_ON_CLOSE); 
     frame.pack(); 
     frame.setVisible(true); 
    } 

    public SortTableWithColors_() { 
     Object[] columnNames = {"B", "C"}; 
     Object[][] data = {{new Integer(1), new Integer(4)}, 
       {new Integer(2), new Integer(5)}, 
       {new Integer(3), new Integer(3)}, 
       {new Integer(4), new Integer(1)}}; 
     // table model 
     DefaultTableModel model = new DefaultTableModel(data, columnNames); 

     // set table model in Jtable 
     JTable table = new JTable(model); 
     table.setAutoCreateRowSorter(true); 
     getContentPane().add(new JScrollPane(table)); 

     // Tell the table what to use to render our columns 
     for (int i = 0; i < 2; i++) { 
      table.getColumnModel().getColumn(i).setCellRenderer(new NewRenderer()); 
     } 
    } 

    // Custom Renderer 
    public class NewRenderer extends DefaultTableCellRenderer { 
     @Override 
     public Component getTableCellRendererComponent 
       (JTable table, Object value, boolean isSelected, 
       boolean hasFocus, int row, int column) { 
      JLabel cell = (JLabel) super.getTableCellRendererComponent 
        (table, value, isSelected, hasFocus, row, column); 

      int rowModel = (int) table.convertRowIndexToModel(row); 
      int colModel = (int) table.convertColumnIndexToModel(column); 
      int rowView = (int) table.convertRowIndexToView(row); 
      int colView = (int) table.convertColumnIndexToView(column); 

      // set color 
      cell.setBackground(new Color(0xFFFFFF)); 
      cell.setForeground(new Color(0x000000)); 

      //set selection colors 
      if (isSelected) { 
       cell.setBackground(new Color(0x4AC3FF)); 
       cell.setForeground(new Color(0x000000)); // AM 
      } 
      // Selective cell colouring based on value 
      int val = (int) value; 
      if (val == 1) { 
       cell.setBackground(Color.GREEN); 
      } 
      return cell; 
     } 
    } 
} 

Antwort

2

Die Reihenfolge der Daten in einem TableModel ist festgelegt.

Die Reihenfolge der Daten in einem JTable kann sich ändern, weil:

  1. die JTable gefiltert werden konnte oder sortiert werden, die der Zeilennummer der JTable bedeutet, können in dem TableModel
  2. ist als die Zeilennummer unterschiedlich sein
  3. der Benutzer könnte die Spalten neu anordnen, was bedeutet, dass die Spaltennummer der JTable von der Spaltennummer in der TableModel abweichen kann.

Es gibt zwei Möglichkeiten, um die Daten zuzugreifen:

  1. die JTable verwenden können Sie: table.getValueAt(...);
  2. die Tablemodel verwenden Sie table.getModel().getValueAt(...);

verwenden können Lassen Sie uns sagen Sie haben Tabelle mit 2 Spalten "FirstName, LastName" und Sie möchten die Daten für die ausgewählte Zeile in einer Datenbank aktualisieren, so dass Sie die Werte für firstName und lastName abrufen müssen.

Beim Umgang mit einem JTable verwenden alle Methoden Zeilen-/Spaltenindizes relativ zur Tabelle. So könnten Sie Code wie verwenden:

String firstName = table.getValueAt(selectedRow, 0); 
String lastName = table.getValueAt(selectedRow, 1); 

Dies funktioniert sogar, wenn die Tabelle sortiert ist oder filtern, da die ausgewählte Zeile in der Tabelle relativ ist.

Was ist jedoch, wenn der Benutzer die zwei Spalten neu anordnet. Der Code wird nicht funktionieren, da die hardcoded Indizes falsch sind. So haben Sie zwei Möglichkeiten:

1) Holen Sie sich die Daten über die JTable aber die Spaltenindizes konvertieren:

String firstName = table.getValueAt(selectedRow, table.convertColumnIndexToView(0)); 
String lastName = table.getValueAt(selectedRow, table.convertColumnIndexToView(1)); 

So, jetzt beide Zeilen/Spalten-Indizes beziehen sich auf den Tisch.

2) Holen Sie sich die Daten über die TableModel, aber dieses Mal sind Sie den Zeilenindex konvertieren müssen:

TableModel model = table.getModel(); 
int modelRow = table.convertRowIndexToModel(selectedRow); 
String firstName = model.getValueAt(modelRow, 0); 
String lastName = model.getValueAt(modelRow, 1); 

ich diesen Ansatz bevorzugen, da nur eine Konvertierung erforderlich ist.

Der Schlüsselpunkt ist, dass Sie niemals alle Konvertierungsmethoden gleichzeitig verwenden würden. Sie müssen entscheiden, ob Sie über die JTable oder die TableModel auf die Daten zugreifen wollen und dann die entsprechende Konvertierung vornehmen.

+0

Danke für die hervorragende Erklärung. Ich bevorzuge es, Daten über Jtable zu verwenden, da gerade bei Sortier- und Filtervorgängen Zeilenindizes am wenigsten beunruhigt sein müssen, besonders beim Definieren von CellRenderer. – Amit

2

Beachten Sie, dass der Renderer row und column Werte sind Ansicht Koordinaten, so dass nur zwei Ihrer Conversions sind sinnvoll:

int rowModel = (int) table.convertRowIndexToModel(row); 
int colModel = (int) table.convertColumnIndexToModel(column); 
//int rowView = (int) table.convertRowIndexToView(row); 
//int colView = (int) table.convertColumnIndexToView(column); 

eine Zeile hinzufügen Modellkoordinaten angezeigt werden in Klammern für die ausgewählte Zeile, um den Effekt zu sehen.Wenn unsortiert sind das Modell und die Ansicht Indices gleich:

if (isSelected) { 
    … 
    System.out.println(row + " (" + rowModel + ") " + column + " (" + colModel +")"); 
} 

Als besonders wachsam sein:

  • Da kann der Benutzer Spalte ändern, um durch Ziehen, konvertieren, wenn das Modell den Zugriff, wie gezeigt für tooltips.

  • Da der Benutzer kann durch Sortierreihen Reihenfolge ändern, umwandeln, wenn das Modell in einem TableCellRenderer Zugriff TableCellEditor oder ListSelectionListener als here gezeigt.