我正在使用DefaultTableModel的扩展,如下所示:
这是更新后的新AchievementTableModel,以反映某些答案的输入。
public AchievementTableModel(Object[][] c, Object[] co) {
super(c,co);
}
public boolean isCellEditable(int r, int c) {return false;}
public void replace(Object[][] c, Object[] co) {
setDataVector(convertToVector(c), convertToVector(co));
fireTableDataChanged();
}
我的GUI是一个具有以下属性的JTable:
if(table==null)
table = new JTable(model);
else
table.setModel(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_ALL_COLUMNS);
table.getTableHeader().setReorderingAllowed(false);
table.getTableHeader().setResizingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
我有一个JComboBox,可以选择要显示的数据。通过调用model.replace(cells)更新TableModel,然后再次运行上面的表创建代码。
当在GUI JTable中选择一行并打印table.getSelectedRow()值时,即使我重新选择,在使用来自第一个选择的model.replace(cells)调用更改表数据后,我总是得到-1第一个JComboBox选项。这是否有理由让我失踪?我应该更改一些代码吗?
编辑:代码在尝试回答此问题时发生了很大变化,因此这里是更新后的代码。新的AchievementTableModel就在上面。这将设置要正确查看的模型和表格并显示在ScrollPane
中if(model==null)
model = new AchievementTableModel(cells, columns);
else
model.replace(cells, columns);
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
} else
table.setModel(model);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
答案 0 :(得分:2)
在调用replace后,您不应该使用新的JTable重新初始化您的表。 fireTableDataChanged()方法将提醒您现有的表应该重绘它。发生的事情是你正在查看放入面板的表,但是你正在将变量更改为不同的JTable实例。当您查询新的但不可见的表时,它将为您提供所选行数的-1。如果您编辑帖子以显示代码区域内的内容,则可能会有所帮助。
第二次修改:
而不是:
if(model==null)
model = new AchievementTableModel(cells, columns);
else
model.replace(cells, columns);
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
} else
table.setModel(model);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
改为:
if(model==null) {
model = new AchievementTableModel(cells, columns);
} else {
model.setDataVector(cells, columns);
}
if(table==null) {
table = new JTable(model);
table.setFillsViewportHeight(true);
table.setAutoResizeMode(JTable.AUTO_RESIZE_OFF);
table.getTableHeader().setReorderingAllowed(false);
table.setSelectionMode(DefaultListSelectionModel.SINGLE_SELECTION);
table.getColumnModel().setColumnSelectionAllowed(false);
table.getTableHeader().setResizingAllowed(false);
column = table.getColumn(columns[0]);
column.setPreferredWidth(25);
column = table.getColumn(columns[1]);
column.setPreferredWidth(225);
column = table.getColumn(columns[2]);
column.setPreferredWidth(40);
table.doLayout();
add(new JScrollPane(table), BorderLayout.CENTER);
} else {
table.setModel(model);
}
您不需要将表格添加到新的滚动窗格中,并在每次模型更改时将其重新添加到面板中。
答案 1 :(得分:2)
好的,现在我很感兴趣
看起来你必须真正清理你的代码,因为周围有很多引用。
您没有看到具有所选索引的表的原因是因为每次创建新的JTable
时,打印所选记录的方法仍指向原始记录。由于您现在正在显示“新”创建的表格,因此旧表格会打印-1
。
使用DefaultTableModel
时获得空表的原因是因为向量是null
(可能是从组合中获得的),因此数据和标题都会从表中消失。
如果您正在使用Object[][]
作为数据,则不需要子类。
所以这是一个更简单的测试类,你可以看到它来纠正你的。
我使用您的自定义 TableModel
和 DefaultTableModel
这与您的自定义表格模型无关,而与您使用引用的方式无关。
我希望这会有所帮助。
import javax.swing.*;
import java.awt.*;
import javax.swing.table.*;
import java.util.*;
import java.awt.event.*;
public class Test {
private DefaultTableModel tableModel = null;
//private AchievementTableModel tableModel = null;
private Object [] headers = new Object[]{"Name", "Last Name"};
private Object [][] data;
private Object [][] dataA = new Object[][]{{"Oscar","Reyes"},{"John","Doe"}};
private Object [][] dataB = new Object[][]{{"Color","Green"},{"Thing","Car"}};
private JTable table;
public static void main( String [] args ) {
Test test = new Test();
test.main();
}
public void main() {
// Create the frame
JFrame frame = new JFrame();
frame.setDefaultCloseOperation( JFrame.EXIT_ON_CLOSE );
// Create the unique table.
table = new JTable();
frame.add(new JScrollPane( table ));
// Add two buttons
frame.add( new JPanel(){{
// swap table model button ( simulates combo )
add(new JButton("Change Table model"){{
addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
if( tableModel == null ) {
data = dataA;
tableModel = new DefaultTableModel( data, headers );
//tableModel = new AchievementTableModel( data, headers );
table.setModel( tableModel );
} else {
data = data == dataA ? dataB : dataA;
tableModel.setDataVector( data, headers );
//tableModel.replace( data ); // not needed DefaultTableModel already has it.
}
}
});
}});
// and print selectedRow button
add( new JButton("Print selected row"){{
addActionListener( new ActionListener() {
public void actionPerformed( ActionEvent e ) {
System.out.println(table.getSelectedRow());
}
});
}});
}}, BorderLayout.SOUTH);
// show the frame
frame.pack();
frame.setVisible( true );
}
}
您的子类未更改。
class AchievementTableModel extends DefaultTableModel {
public AchievementTableModel(Object[][] c, Object[] co) {
super.dataVector = super.convertToVector(c);
super.columnIdentifiers = super.convertToVector(co);
}
public int getColumnCount() {return super.columnIdentifiers.size();}
public int getRowCount() {return super.dataVector.size();}
public String getColumnName(int c) {return (String)super.columnIdentifiers.get(c);}
@SuppressWarnings("unchecked")
public Object getValueAt(int r, int c) {return ((Vector<Object>)super.dataVector.get(r)).get(c);}
public boolean isCellEditable(int r, int c) {return false;}
public void replace(Object[][] c) {
super.dataVector = super.convertToVector(c);
super.fireTableDataChanged();
}
}
尝试一下,看看它如何不会丢失表格参考,并始终打印正确的selectedRow
。
将它与您的代码进行比较并从那里修复它。
答案 2 :(得分:1)
当它交换数据时,它删除了选择(因为索引现在不同),你需要重新计算选择并以编程方式设置它。
我会指出,根据我的经验,这就是为什么我倾向于扩展AbstractTableModel
或者从头开始实现我自己的TableModel
接口。像这里修改后备数据引用,总会导致一百万个问题恕我直言。
答案 3 :(得分:1)
也许尝试使用
super.setDataVector(Vector dataVector,Vector ColumnNames);
javax.swing.table.DefaultTableModel
public void setDataVector(Vector dataVector, Vector columnIdentifiers)
来自JavaDoc
替换当前的dataVector 带有新Vector的实例变量 行,dataVector。每一行都是 在dataVector中表示为Vector 对象值。 columnIdentifiers 是新列的名称。该 columnIdentifiers中的名字是 映射到dataVector中的第0列。每 dataVector中的行被调整为匹配 中的列数 columnIdentifiers要么截断 Vector如果太长,或者 如果太短,则添加空值。 请注意,传入null值 dataVector导致未指定 行为,可能是一个例外。 参数:dataVector - 新数据 vector columnIdentifiers - 名称 列
答案 4 :(得分:0)
重新排序JTable时,需要跟踪TableModel中数据的原始索引,而不是JTable上的当前索引。在视觉上,表可能已经移位,但基础数据模型没有。
答案 5 :(得分:0)
听到更改您的选择时丢失了。
“getSelectedRow()”是否会在更改模型后“返回”之前返回任何内容?
如果是,则保持该索引,更改模型,然后再次设置该索引。
您可能需要为该
使用自定义ListSelectionModel答案 6 :(得分:0)
我想到的另一件事是,当你执行table= new JTable(model);
时,你正在更改变量'table'所引用的表,但是这可能不会自动导致新表被渲染。
如果您的表包含在ScrollPane中,则可能需要调用ScrollPane.setViewportView(table);
答案 7 :(得分:0)
我有同样的问题,总是为getSelectedRow()得到-1。这个问题现在可以解决了。尽管如此,发布修复我的问题的代码:
final int selectedRowIndex = table.rowAtPoint(mouseEvent.getPoint());
final int modelRowIndex = table.convertRowIndexToModel(selectedRowIndex);