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

时间:2015-08-24 14:32:25

标签: 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);

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

enter image description here

我从未使用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);
  }
}

效果很好。

enter image description here

很容易对尺寸列进行右对齐:

rightRenderer = new DefaultTableCellRenderer();
rightRenderer.setHorizontalAlignment(SwingConstants.RIGHT);

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

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

          String entry = (String)tblOutput.getValueAt(row, 3) 
                + "\\" + (String)tblOutput.getValueAt(row, 2);

我不知道为什么它一直存在,因为我偷了所有的东西 来自不同地方的各种代码。

无论如何,现在一切正常。

但我有疑问:

(1)在获取表格行的值的上下文中何时需要getModel?     我认为dftTableModel tblOutput用于getModel肯定是正确的。

(2)TableRowSorter返回的行是数据最初所在的行吗?     如果是这样,我想这有时会很有用。不知道什么时候......要“取消排序”?

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

(4)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;

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

程序的

导入:

            OleDbConnection accCon = new OleDbConnection();
            OdbcCommand mySQLCon = new OdbcCommand();
            try
            {
                //connect to mysql
                Connect();
                mySQLCon.Connection = connection;

                //connect to access
                accCon.ConnectionString = @"Provider=Microsoft.Jet.OLEDB.4.0;" +
                                          @"Data source= " + pathToAccess;
                accCon.Open();
                var cnt = 0;

                while (cnt < 5)
                {
                    if (accCon.State == ConnectionState.Open)
                        break;
                    cnt++;
                    System.Threading.Thread.Sleep(50);
                }

                if (cnt == 5)
                {
                    ToolBox.logThis("Connection to Access DB did not open. Exit Process");
                    return;
                }
            }
            catch (Exception e)
            {
                ToolBox.logThis("Faild to Open connections. msg -> " + e.Message + "\\n" + e.StackTrace);
            }
//AMK: transaction starts here
            var transaction = accCon.BeginTransaction();
            OleDbCommand accCmn = new OleDbCommand();

            accCmn.Connection = accCon;
            accCmn.Transaction = transaction;
//access insert query structure
            var insertAccessQuery = "INSERT INTO {0} values({1});";
// key = > tbl name in access, value = > mysql query to b executed
            foreach (var table in tblNQuery)
            {
                try
                {
                    mySQLCon.CommandText = table.Value;
                    //executed mysql query                        
                    using (var dataReader = mySQLCon.ExecuteReader())
                    {
                        //variable to hold row data
                        var rowData = new object[dataReader.FieldCount];
                        var parameters = "";
                        //read the result set from mysql query
                        while (dataReader.Read())
                        {
                            //fill rowData with the row values
                            dataReader.GetValues(rowData);
                            //build the parameters for insert query
                            for (var i = 0; i < dataReader.FieldCount; i++)
                                parameters += "'" + rowData[i] + "',";

                            parameters = parameters.TrimEnd(',');
                            //insert to access
                            accCmn.CommandText = string.Format(insertAccessQuery, table.Key, parameters);
                            try
                            {
                                accCmn.ExecuteNonQuery();
                            }
                            catch (Exception exc)
                            {
                                ToolBox.logThis("Faild to insert to access db. msg -> " + exc.Message +
                                                "\\n\\tInsert query -> " + accCmn.CommandText);
                            }
                            parameters = "";
                        }
                    }
//AMK: transaction commits here if every thing is going well
                    transaction.Commit();
                }
                catch (Exception e)
                {
                    ToolBox.logThis("Faild to populate access db. msg -> " + e.Message + "\\n" + e.StackTrace);
//AMK: transaction rollback here if there is a problem
                    transaction.Rollback();
                }
            }
            Disconnect();
            accCmn.Dispose();
            accCon.Close();

2 个答案:

答案 0 :(得分:3)

  

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

table.getValueAt(row, column); 中的数据未排序。 View(JTable)以排序顺序显示数据

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

int modelRow = table.convertRpwIndexToModel(row);
table.getModel().getValueAt(modelRow, column);

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

JTable

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

因此,您始终需要知道您是否尝试按TableModel上显示的方式或其加载到String entry = (String)tblOutput.getValueAt(row, 3) ... 的方式访问数据,然后使用适当的索引(或可能)不涉及索引转换。

getValueAt(...)

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

所以在上面的陈述中你需要转换&#34; 3&#34;从模型到视图,因为您正在使用表的int viewColumn3 = table.convertColumnIndexToView(3); String entry = (String)tblOutput.getValueAt(row, viewColumn3) 方法。

String entry = (String)tblOutput.getModel().getValueAt(modelRow, 3) ... 

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

        protected IActorRef concertRouter;


    public User(IActorRef concertRouter, int eventId)
    {
        this.concertRouter = concertRouter;
        this.eventId = eventId;

        JobStarter = Context.System.Scheduler.ScheduleTellRepeatedlyCancelable(TimeSpan.FromMilliseconds(20),
                     TimeSpan.FromMilliseconds(1000), Self, new AttemptToStartJob(), Self);

        Receive<AttemptToStartJob>(start =>
        {
            var self = Self;

            concertRouter.Ask<Routees>(new GetRoutees()).ContinueWith(tr =>
            {
                if (tr.Result.Members.Count() > 0)
                {
                    var m = new GetAvailableSeats() { User = self, ConcertId = eventId };

                    self.Tell(m);

                    //                        JobStarter.Cancel();                      

                }

            }, TaskContinuationOptions.ExecuteSynchronously);
        });

        Receive<GetAvailableSeats>(rs =>
        {
            rs.User = Self;

            //get free seats
            concertRouter.Ask(rs).ContinueWith(t=>
            {
                Console.WriteLine("response received!!");

            }
            );
        });

答案 1 :(得分:0)

这就是现在的SSCCE(见评论),但它是基于@camickr上下文评论中建议的原始代码的修订版。

此问题已修复目前,拖动列后,如果文件名或路径列位置发生更改,则单击按钮会导致错误,例如The file: xml\C:\Users\Dov\.AndroidStudio1.2\config\options doesn't exist.移动扩展列后发生此错误(其中在Filename列之前)到Path列之后。

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;

public class RowSorterWithComparator 
{
  static final int    DATE_COLUMN     = 0;
  static final int    SIZE_COLUMN     = 1;
  static final int    EXTENSION_COLUMN= 2;
  static final int    FILENAME_COLUMN = 3;
  static final int    PATH_COLUMN     = 4;

  public static void main(String args[]) 
  {
    Comparator               compareNumericStringsWithCommas;
    TableRowSorter           sorter;
    JTable                   tblOutput;
    JScrollPane              pane;
    JFrame                   frame;
    DefaultTableModel        dftTableModel; 
//    TableColumnAdjuster      tca ;
    DefaultTableCellRenderer rightRenderer;
    JButton                  btnOpen;

    Object[] columnNames = new Object[]{"Date", "Size", "Extension", "File name", "Path to file"};
    Object rows[][] = 
      {
      {"7/27/2015","9,600","xml","mavenVersion.xml","C:/Users/Dov/.AndroidStudio1.2/config/options/"},
      {"7/27/2015","120,000","xml","keymap.xml","C:/Users/Dov/.AndroidStudio1.2/config/options/"},
      {"7/27/2015","108","xml","Default.xml","C:/Users/Dov/.AndroidStudio1.2/config/inspection/"},
      {"4/27/2015","39,200","txt","key pay.txt","C:/Users/Dov/A/"},
      {"6/13/2015","91","java","BuildConfig.java","C:/Users/Dov/androidfp2_examples/eclipse_projects/FlagQuiz/gen/com/deitel/flagquiz/"}
      };

    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(columnNames);

    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 (Object[] row : rows)
      dftTableModel.addRow(row);

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

    btnOpen.addMouseListener(new MouseAdapter() 
    {
        @Override
        public void mouseClicked(MouseEvent e)
        {       
          int viewFilenameCol = tblOutput.convertColumnIndexToView(FILENAME_COLUMN);
          int viewPathCol     = tblOutput.convertColumnIndexToView(PATH_COLUMN);
          int row = tblOutput.getSelectedRow();
          String entry = (String)tblOutput.getValueAt(row, viewPathCol) 
                      +  (String)tblOutput.getValueAt(row, viewFilenameCol);
          try 
          {
            Desktop.getDesktop().open(new File((entry.trim())));
          } 
          catch 
          (
            Exception ex) {System.out.println("Can't open file <" + entry + ">"); 
          }
      }
    });

    frame = new JFrame("Sort Table Demo");
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.add(pane, BorderLayout.CENTER);
    frame.add(btnOpen, BorderLayout.SOUTH);
    frame.setSize(800, 350);
    frame.setVisible(true);
  }
}