JTable повторяющиеся значения в строке
У меня есть JTable
заполнены обычаем DataModel
(вставлено ниже) и когда я звоню populate()
По- видимому, метод заполняет таблицу дублирующимися данными - каждая строка заполняется одним и тем же значением снова и снова. Однако при ближайшем рассмотрении (просто путем println() в поле "data") модель данных не ошибается - она содержит правильные данные в том формате, который я ожидаю. Что дает?
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();
}
}
3 ответа
Вот полный пример, который может оказаться полезным. Как образец Map
не поддается изменению, я отсылаю вас к примеру @mKorbel о том, как переопределить 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://stackru.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();
}
});
}
}
Вы можете попытаться сделать изменения в населении более атомарными.
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
изменяется во время его итерации.
1) твой TableModel
un_completed, я скучаю там много или необходимые методы для JTable's
жизненный цикл, начиная с TableHeader
и т.п.
2) так как существует множество AbstactTableModels, основанных на HashMap, я бы предложил возвращать тип массивов, реализованный непосредственно в API.
Vector<Vector<Object or String>> data;
String[][] or Object[][]
вместо
ArrayList<ArrayList<String>> data;
простое объяснение состоит в том, что XxxList возвращает столбец, а Vector или String[] возвращают строку
3) Я бы предложил использовать DefaultTableModel
непосредственно тогда вам никогда не придется решать дубликаты или пропущенные столбец / строку