带比较器的 JTable 在排序后访问了错误的行数据;删除 getModel() 修复了它。为什么?

DSl*_*r64 1 java swing jtable comparator

为我的项目引入排序非常容易JTable

  //Existing code
  dftTableModel = new DefaultTableModel(0 , 4);
  tblOutput     = new JTable(dftTableModel);

  //Added code
  RowSorter<TableModel> sorter = new TableRowSorter<TableModel>(dftTableModel);
  tblOutput.setRowSorter(sorter);
Run Code Online (Sandbox Code Playgroud)

但由于我将Size列格式化为带逗号的文本,因此它没有排序:

在此输入图像描述

我从未使用过,Comparator但找到了一个我修改过的示例。

public class RowSorterWithComparator 
{
  static Comparator               compareNumericStringsWithCommas;
  static TableRowSorter           sorter;
  static JTable                   tblOutput;
  static JScrollPane              pane;
  static JFrame                   frame;
  static DefaultTableModel        dftTableModel; 
//  static TableColumnAdjuster      tca ;
  static DefaultTableCellRenderer rightRenderer;
  static JButton                  btnOpen;

  static String[] columnNames = { "Date", "Size" };
  static Object rows[][] = 
{
{"7/27/2015","96","mavenVersion.xml","C:\\Users\\Dov\\.AndroidStudio1.2\\config\\options\\"},
{"7/27/2015","120","keymap.xml","C:\\Users\\Dov\\.AndroidStudio1.2\\config\\options\\"},
{"7/27/2015","108","Default.xml","C:\\Users\\Dov\\.AndroidStudio1.2\\config\\inspection\\"},
{"4/27/2015","392","key pay.txt","C:\\Users\\Dov\\A\\"},
{"6/13/2015","161","BuildConfig.java","C:\\Users\\Dov\\androidfp2_examples\\eclipse_projects\\FlagQuiz\\gen\\com\\deitel\\flagquiz\\"}
};

  public static void main(String args[]) 
  {
    compareNumericStringsWithCommas = (Comparator) new Comparator() 
    {
      @Override public int compare(Object oo1, Object oo2) 
      {
        String o1 = oo1.toString().replace(",", "");
        String o2 = oo2.toString().replace(",", "");
        return Integer.valueOf(o1).compareTo(Integer.valueOf(o2));
      }
    };

    dftTableModel = new DefaultTableModel(0 , columnNames.length);
    tblOutput     = new JTable(dftTableModel);
    dftTableModel.setColumnIdentifiers(new Object[]{"Date", "Size", "File name", "Path to file"});

    rightRenderer = new DefaultTableCellRenderer();
    rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
    tblOutput.getColumnModel().getColumn(1).setCellRenderer(rightRenderer);

    sorter      = new TableRowSorter<>(dftTableModel);
    sorter.setModel(tblOutput.getModel());
    sorter.setComparator(1,compareNumericStringsWithCommas);

    tblOutput.setRowSorter(sorter);
    tblOutput.setAutoResizeMode(AUTO_RESIZE_OFF);

//    tca = new tablecolumnadjuster.TableColumnAdjuster(tblOutput);
//    tca.setDynamicAdjustment(true);

    tblOutput.setFont(new Font("Courier New",Font.PLAIN,12));

    pane = new JScrollPane(tblOutput);

    for (int i = 0; i < 5; i++)
      dftTableModel.addRow(rows[i]);

    btnOpen = new JButton("Open selected file");

    btnOpen.addMouseListener(new MouseAdapter() {
        @Override
        public void mouseClicked(MouseEvent e)
        {       
          int row = tblOutput.getSelectedRow();
          String entry = (String)tblOutput.getModel().getValueAt(row, 3) 
                + "\\" + (String)tblOutput.getModel().getValueAt(row, 2);
          try 
          {
            Desktop.getDesktop().open(new File((entry.trim())));
          } catch (IOException ex) {System.out.println("Can't open file"); }
      }
    });

    frame = new JFrame("Sort Table Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(pane, BorderLayout.CENTER);
    frame.add(btnOpen, BorderLayout.AFTER_LAST_LINE);
    frame.setSize(800, 350);
    frame.setVisible(true);
  }
}
Run Code Online (Sandbox Code Playgroud)

效果很好。

在此输入图像描述

右对齐大小列很容易:

rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT);
Run Code Online (Sandbox Code Playgroud)

我添加了一个按钮来打开所选文件。但排序后,打开了错误的文件。

所以我getModel从鼠标监听器中删除了语句:

          String entry = (String)tblOutput.getValueAt(row, 3) 
                + "\\" + (String)tblOutput.getValueAt(row, 2);
Run Code Online (Sandbox Code Playgroud)

我不知道它为什么在那里,因为我一直在从不同的地方窃取各种代码。

不管怎样,现在一切正常了。

但我有疑问:

(1)getModel在获取表行值的上下文中什么时候需要?我认为“since”dftTableModel用于tblOutput此目的肯定是正确的。

(2) 返回的行是否是getModel数据原来所在的行?如果是这样,我想这有时可能会有用。不确定什么时候......“取消排序”?

(3)是否是我使用的原因TableRowSorter没有getModel得到正确的数据?(即,两者不兼容吗?)

(4)dftTableModel相当于tblOutput.getModel()

......................................

程序的导入:

import java.awt.BorderLayout;
import java.awt.Desktop;
import java.awt.Font;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.io.File;
import java.io.IOException;
import java.util.Comparator;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import static javax.swing.JTable.AUTO_RESIZE_OFF;
import javax.swing.SwingConstants;
import javax.swing.table.DefaultTableCellRenderer;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableRowSorter;
//import tablecolumnadjuster.TableColumnAdjuster;
Run Code Online (Sandbox Code Playgroud)

cam*_*ckr 5

所以我从鼠标监听器中的语句中删除了 getModel :

中的数据TableModel未排序。视图(JTable)按排序顺序显示数据

您可以使用以下方法从视图中获取数据:

table.getValueAt(row, column);
Run Code Online (Sandbox Code Playgroud)

如果你想从你使用的 TableModel 获取数据:

int modelRow = table.convertRpwIndexToModel(row);
table.getModel().getValueAt(modelRow, column);
Run Code Online (Sandbox Code Playgroud)

还有一些来回转换列索引的方法。

因此,您始终需要知道您是否正在尝试以数据显示的方式访问数据,JTable或者以数据加载的方式访问数据TableModel,然后使用可能(或可能)不涉及索引转换的适当索引。

String entry = (String)tblOutput.getValueAt(row, 3) ...
Run Code Online (Sandbox Code Playgroud)

当您对值进行硬编码时,您需要知道硬编码值代表什么。在这种情况下,您将访问表中的动态行值和模型中的列。

因此,在上面的语句中,您需要将“3”从模型转换为视图,因为您使用的是getValueAt(...)表的方法。

int viewColumn3 = table.convertColumnIndexToView(3);
String entry = (String)tblOutput.getValueAt(row, viewColumn3) 
Run Code Online (Sandbox Code Playgroud)

或者,由于您多次引用硬编码值(即第 2 列和第 3 列),因此保留硬编码列索引并仅转换行索引一次,然后从 TableModel 访问数据可能会更容易:

String entry = (String)tblOutput.getModel().getValueAt(modelRow, 3) ... 
Run Code Online (Sandbox Code Playgroud)