我有JTable
填充了自定义DataModel
(粘贴在下方),当我调用populate()
方法时,出现以填充表格重复数据 - 每一行都反复填充相同的值。然而,仔细检查(通过简单地println()'数据'字段),数据模型没有错 - 它以我期望的格式保存正确的数据。是什么给了什么?
import java.util.ArrayList;
import javax.swing.table.AbstractTableModel;
@SuppressWarnings("serial") // we don't expect this app to ever use serialized classes. EVER.
public class CollectionDataModel extends AbstractTableModel {
private ArrayList<ArrayList<String>> data;
public CollectionDataModel() {
data = new ArrayList<ArrayList<String>>();
}
@Override
public int getColumnCount() {
if(data.isEmpty()) return 0;
return data.get(0).size();
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int rowIndex, int columnIndex) {
if(rowIndex > getRowCount()) return null;
if(columnIndex > getColumnCount()) return null;
return data.get(rowIndex).get(columnIndex);
}
public void populate(Collection c) {
data.clear();
for(Item i : c.getItems()) {
ArrayList<String> row = new ArrayList<String>();
for(Property p : i.getProperties().values()) {
row.add(p.toString());
}
data.add(row);
}
fireTableDataChanged();
}
}
答案 0 :(得分:10)
这是一个可能有用的完整示例。由于示例Map
是不可修改的,因此我会向您推荐@ mKorbel的example,了解如何覆盖isCellEditable()
和setValueAt()
。
import java.awt.EventQueue;
import java.awt.GridLayout;
import java.util.Map;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTable;
import javax.swing.table.AbstractTableModel;
/** @see https://stackoverflow.com/questions/9132987 */
public class EnvTableTest extends JPanel {
public EnvTableTest() {
this.setLayout(new GridLayout());
this.add(new JScrollPane(new JTable(new EnvDataModel())));
}
private static class EnvDataModel extends AbstractTableModel {
private Map<String, String> data = System.getenv();
private String[] keys;
public EnvDataModel() {
keys = data.keySet().toArray(new String[data.size()]);
}
@Override
public String getColumnName(int col) {
if (col == 0) {
return "Key";
} else {
return "Value";
}
}
@Override
public int getColumnCount() {
return 2;
}
@Override
public int getRowCount() {
return data.size();
}
@Override
public Object getValueAt(int row, int col) {
if (col == 0) {
return keys[row];
} else {
return data.get(keys[row]);
}
}
}
private void display() {
JFrame f = new JFrame("EnvTableTest");
f.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
f.add(this);
f.pack();
f.setLocationRelativeTo(null);
f.setVisible(true);
}
public static void main(String[] args) {
EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
new EnvTableTest().display();
}
});
}
}
答案 1 :(得分:3)
您可以尝试更改填充更多原子。
public void populate(Collection c) {
ArrayList<ArrayList<String>> data2 = new ArrayList<ArrayList<String>>();
for(Item i : c.getItems()) {
ArrayList<String> row = new ArrayList<String>();
for(Property p : i.getProperties().values()) {
row.add(p.toString());
}
data2.add(row);
}
data = data2;
fireTableDataChanged();
}
我猜测在populate
之前的呼叫结束之前再次调用populate
。可能c
在迭代期间发生了变化。
答案 2 :(得分:2)
1)您的TableModel
未完成,我错过了JTable's
生命周期的许多或必需的方法,从TableHeader
等开始。
2)因为有很多基于HashMap的AbstactTableModel,我建议直接返回在API中实现的数组类型
Vector<Vector<Object or String>> data;
String[][] or Object[][]
而不是
ArrayList<ArrayList<String>> data;
简单的解释是XxxList returs列和Vector或String []返回Row
3)我建议直接使用DefaultTableModel
然后你永远不需要解决重复或错过列/行