我有一个名为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();
}
}
}
答案 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);
}
}