2016-04-15 12 views
0

这是一个难以解释的问题,我会尝试并逐步解释它,并排运行代码将有所帮助,但查看图像应该足以理解我的问题。行,模型行和视图行的有趣行为 - 哪一个使用时?

row和rowModel分别与数据显示和数据模型一致,但我根本无法理解rowView。什么时候rowView会有用?

1)默认视图:列B(1,2,3,4)。

enter image description here

2)按此排序列B报头:升序(1,2,3,4)。始终dataRow = modelRow = viewRow。

3)单击以对列B标题进行排序:按降序排列(4,3,2,1)。

行0 = rowModel 3 = rowView 3

行1 = rowModel 2 = rowView 2

行2 = rowModel 1 = rowView 1

行3 = rowModel 0 = rowView 0

所有预期!

4)现在点击列C进行排序:排序升序(下图)

enter image description here

列0:值 “4” - 行0 = rowModel 3 = rowView 2 ---为什么rowView是2?

第1列:值“1” - 行0 = rowModel 3 = rowView 2 --- 为什么rowView是2并且在剩余单元格中的行为如下?

列0:值“3” - 行1 = rowModel 2 = rowView 3 ---为什么rowView是3?

列1:值“3” - 行1 = rowModel 2 = rowView 3 ---为什么rowView是3?

列0:值“1” - 行2 = rowModel 0 = rowView 1 ---为什么rowView是1?

列1:值“4” - 行2 = rowModel 0 = rowView 1 ---为什么rowView是1?

列0:值“2” - 行3 = rowModel 1 = rowView 0 ---为什么rowView是0?

列1:值“5” - 行3 = rowModel 1 = rowView 0 ---为什么rowView是0?

代码:

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

回答

2

TableModel中的数据顺序是固定的。

的数据在JTable的顺序可以改变,因为:

  1. JTable可以筛选或排序,这意味着JTable的行数可以比在TableModel
  2. 行数不同
  3. 用户可以对列进行重新排序,这意味着JTable的列号可以与TableModel中的列号不同。

有两种方法来访问数据:

  1. 使用JTable中可以使用:table.getValueAt(...);
  2. 使用TableModel中您可以使用table.getModel().getValueAt(...);

比方说你有一个包含2列“FirstName,LastName”的表,并且希望将数据更新到选定行的数据库,因此您需要获取firstName和lastName的值。

处理JTable时,所有方法都使用相对于表的行/列索引。因此,您可能会使用如下代码:

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

即使对表进行排序或过滤,由于所选行与表相关,所以这将起作用。

但是,如果用户重新排列这两列,该怎么办。代码将不会工作,因为 硬编码索引将是错误的。所以,你有两个选择:

1)通过JTable获取数据,但转换列索引:

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

所以现在都行/列的索引是相对于表。

2)获得通过TableModel的数据,但这个时候,你需要的行索引转换:

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

我喜欢这种方法,因为只需要一个转换。

关键是你永远不会同时使用所有的转换方法。您需要决定是否要通过JTableTableModel访问数据,然后进行适当的转换。

+0

感谢您的优秀解释。我更喜欢通过Jtable使用数据,因为在排序和过滤操作期间,行索引是最不需要担心的,特别是在定义单元格渲染器时。 – Amit

2

注意渲染器的rowcolumn视图坐标,所以只有两个您的转换是有意义的:

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

添加一行中显示模型的坐标在所选行的括号内查看效果。当未排序,模型和视图指数是相同的:

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

时要特别警惕:

  • 因为用户可以通过拖动改变列顺序,转换访问如图所示为模型时tooltips

  • 因为用户可以通过排序改变行顺序,在转换一个TableCellRendererTableCellEditorListSelectionListener访问如图所示here模型时。