用户对列进行排序后访问隐藏的JTable模型列

时间:2014-01-10 06:58:18

标签: java swing model jtable tablemodel

我有一个名为JTable的{​​{1}},每行代表transactionList,其中第一列包含实际的Transaction对象,后面的每一列都显示有关{的Transaction对象的一些数据{1}}。

我不希望Transaction对象显示给用户,因此我将其从Transaction中删除:

ColumnModel

这很好用,然后我可以使用:

检索选定的TableColumnModel cm = transactionList.getColumnModel(); cm.removeColumn(cm.getColumn(0)); transactionList.setColumnModel(cm);
Transaction

当用户对表中的列进行排序,然后所选行与正确匹配时,问题就开始了。我通过更改上面的行来解决这个问题,以便我们直接从表中获取所选行,而不是从模型中获取:

(Transaction) transactionList.getModel().getValueAt(transactionList.getSelectedRow(), 0))

但现在0列不是我隐藏的(Transaction) transactionList.getValueAt(transactionList.getSelectedRow(), 0)); 对象,而只是它的第一个字段。


我也会尝试用另一种方式解释。

不允许对JTable列进行排序,两个示例都有效:

1)在第一列中显示事务对象(不要从ColumnModel中删除)

可以使用以下命令检索Transaction对象:

Transaction

2)在第一列中显示事务对象(从ColumnModel中删除)

可以使用以下命令检索Transaction对象:

transactionList.getValueAt(transactionList.getSelectedRow(), 0));

如果我现在允许对列进行排序,#1仍然有效。但是,方法#2现在将JTable.getSelectedRow()传递给TableModel.getValueAt()。这些索引不再相等,问题是JTable和ColumnModel不包含Transaction对象(只有TableModel会这样做)。

transactionList.getModel().getValueAt(transactionList.getSelectedRow(), 0))

我看到的一个可能的解决方案是在用户单击列标题时对TableModel和JTable进行排序。这可行吗?有没有更好的方法来实现这个目标(将一个“隐藏”对象附加到JTable行)?


的TableModel

transactionList.getColumnCount(); //return 5
transactionList.getColumnModel().getColumnCount(); //return 5
transactionList.getModel().getColumnCount(); //returns 6

MCVE

隐藏的第一列与第二列具有匹配值。使用未排序的JTable时,按钮会打印正确的值,但在通过单击标题对列进行排序后,模型将不同步。

public class TransactionTableModel extends AbstractTableModel {
    String[] columnNames = { "<Transaction_Object>", "Date", "Name",
            "Hours", "Amount", "Notes" };

    public TransactionTableModel() {
    }
    public String getColumnName(int col) {
        return columnNames[col].toString();
    }

    public Class<?> getColumnClass(int col) {
        switch (col) {
        case 1:
            return Calendar.class;
        case 2:
            return String.class;
        }
    }

    public int getRowCount() {
        return DB.getInstance().getTransactions().size();
    }

    public int getColumnCount() {
        return columnNames.length;
    }

    public Object getValueAt(int row, int col) {
        Transaction t = null;
        t = DB.getInstance().getTransactionsChronological().get(row);
        switch (col) {
        case 0:
            return t;
        case 1:
            return t.getDate();
        case 2:
            return t.getStudent.getName();
        }
    }
}

2 个答案:

答案 0 :(得分:3)

要记住的一件事是JTable和TableModel有两个独立的坐标系,即视图与模型系统:

  • 列索引可能因重新排序而有所不同
  • 行索引可能因排序/过滤而有所不同

JTable有方法convertRow / ColumnToView / Model来回映射,以获取访问所选(view!)行的模型行的具体问题:

model.getValueAt(table.convertRowIndexToModel(table.getSelectedRow()), 0);

答案 1 :(得分:2)

  

我是否正确使用桌子?

没有。为此,我将创建一个自定义TransactionTableModel,它接受​​Transaction个对象的集合,并根据需要创建完全相同的列,以显示相关的Transaction详细信息。

有关详细信息,请参阅Creating a Table Model

可能有点像这样:

import java.awt.*;
import java.awt.event.*;
import java.util.Vector;
import javax.swing.*;
import javax.swing.event.ListSelectionListener;
import javax.swing.event.TableModelListener;
import javax.swing.table.*;

public class SwingTesting {

    JFrame frame;
    TablePane tablePane;

    public SwingTesting() {
        tablePane = new TablePane();

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);

        JButton test = new JButton("Print hidden item");
        test.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                //printHiddenItem();
            }
        });

        frame.add(tablePane);
        frame.add(test, BorderLayout.SOUTH);
        frame.pack();
        frame.setVisible(true);
    }

    class TablePane extends JPanel {

        private final JTable table;
        private final ListSelectionModel listSelectionModel;

        public TablePane() {
            super(new BorderLayout());
            Vector<Vector<Transaction>> transactions =
                    new Vector<Vector<Transaction>>();
            addTransactionToVector(
                    transactions, new Transaction("ONE", "ONE", "2007"));
            addTransactionToVector(
                    transactions, new Transaction("TWO", "TWO", "2012"));
            addTransactionToVector(
                    transactions, new Transaction("THREE", "THREE", "2009"));
            addTransactionToVector(
                    transactions, new Transaction("FOUR", "FOUR", "2005"));
            addTransactionToVector(
                    transactions, new Transaction("FIVE", "FIVE", "2001"));

            Vector<String> columnNames = new Vector<String>();
            columnNames.add("Column 1");
            columnNames.add("Column 2");
            columnNames.add("Year");

            table = new JTable(
                    new TransactionTableModel(transactions, columnNames));

            listSelectionModel = new DefaultListSelectionModel();
            table.setSelectionModel(listSelectionModel);
            table.setSelectionMode(ListSelectionModel.SINGLE_INTERVAL_SELECTION);

            table.setAutoCreateRowSorter(true);
            table.setFillsViewportHeight(true);

            this.add(new JScrollPane(table));
        }

        private void addTransactionToVector(
                Vector<Vector<Transaction>> transactions, Transaction transaction) {
            Vector<Transaction> transactionVector = new Vector<Transaction>();
            transactionVector.add(transaction);
            transactions.add(transactionVector);
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {

            public void run() {
                new SwingTesting();
            }
        });
    }
}

class Transaction {

    String number1;
    String number2;
    String year;

    Transaction(String number1, String number2, String year) {
        this.number1 = number1;
        this.number2 = number2;
        this.year = year;
    }

    public String toString() {
        return "Transaction:- number1: "
                + number1
                + " number2: "
                + number2
                + " year: "
                + year;
    }
}

class TransactionTableModel extends DefaultTableModel {

    TransactionTableModel(
            Vector<Vector<Transaction>> transactions,
            Vector<String> columnNames) {
        super(transactions, columnNames);
    }

    @Override
    public int getColumnCount() {
        return 3;
    }

    @Override
    public Class<?> getColumnClass(int columnIndex) {
        return String.class;
    }

    @Override
    public Object getValueAt(int rowIndex, int columnIndex) {
        Object o = super.getValueAt(rowIndex, 0);
        Transaction transaction = (Transaction)o;
        switch (columnIndex) {
            case 0:
                return transaction.number1;
            case 1:
                return transaction.number2;
            case 2:
                return transaction.year;
            default:
                return null;
        }
    }

    @Override
    public void setValueAt(Object aValue, int rowIndex, int columnIndex) {
        Transaction transaction = (Transaction)aValue;
        Vector<Transaction> values = new Vector<Transaction>();
        values.add(transaction);
        super.setValueAt(aValue, rowIndex, 0);
    }
}