Что вы используете в качестве значений в TableModel
?
Одним из решений было бы определение класса, скажем CategoryValue
, который представляет список возможных элементов и выбранного элемента, и использование этого; затем прослушайте TableModelEvents
и, когда значение в столбце 0 изменится, установите соответствующее значение в столбце 1. Ниже приведен простой пример.
Сначала TableModelListener
:
model.addTableModelListener(new TableModelListener() {
@Override
public void tableChanged(TableModelEvent e) {
if (e.getColumn() == 0) {
int firstRow = e.getFirstRow();
int lastRow = e.getLastRow();
for (int row = firstRow; row <= lastRow; row++) { // note <=, not <
CategoryValue parentValue = ((CategoryValue) model.getValueAt(row, 0));
String parentSelection = parentValue.getSelection();
List<String> childCategories = getChildCategories(parentSelection);
CategoryValue newChildValue = new CategoryValue(childCategories);
model.setValueAt(newChildValue , row, 1);
}
}
}
});
(Реализация getChildCategories(String)
зависит от того, откуда поступают ваши данные, но это может быть так же просто, как Map<String, List<String>>
.)
Далее класс значений:
public class CategoryValue {
private final String selection;
private final List<String> categories;
public CategoryValue(List<String> categories) {
this(categories, categories.get(0));
}
public CategoryValue(List<String> categories, String selection) {
assert categories.contains(selection);
this.categories = categories;
this.selection = selection;
}
public String getSelection() {
return selection;
}
public List<String> getCategories() {
return categories;
}
@Override
public String toString() {
return selection;
}
}
Наконец, пользовательский редактор ячеек для класса значений:
public class CategoryCellEditor extends DefaultCellEditor {
public CategoryCellEditor() {
super(new JComboBox());
}
static List<CategoryValue> allValues(List<String> categories) {
List<CategoryValue> allValues = new ArrayList<CategoryValue>();
for (String value: categories) {
allValues.add(new CategoryValue(categories, value));
}
return Collections.unmodifiableList(allValues);
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value,
boolean isSelected, int row, int column) {
CategoryValue categoryValue = (CategoryValue) value;
List<String> categories = categoryValue.getCategories();
List<CategoryValue> allValues = CategoryValue.allValues(categories);
ComboBoxModel cbModel = new DefaultComboBoxModel(allValues.toArray());
((JComboBox)editorComponent).setModel(cbModel);
return super.getTableCellEditorComponent(table, categoryValue,
isSelected, row, column);
}
}
Все сделано с одним прослушивателем событий, и приятным бонусом является то, что этому прослушивателю событий не важно, как таблица редактируется / обновляется или откуда происходят изменения / обновления.
Отредактировано, чтобы добавить: В качестве альтернативы, представьте каждую строку таблицы с некоторым бизнес-объектом, который фиксирует все выборы, сделанные для конкретной строки, и получите CellEditor
для получения доступных вариантов из бизнес-объекта (используя аргумент row
для getTableCellEditorComponent()
, чтобы получить бизнес-объект). Механизм событий останется прежним. Преимущество этого состоит в том, что, вероятно, легче читать выбранные значения из бизнес-объекта, чем очищать таблицу.