Java JTable中的依赖列
嗨! 我有一张表格。此JTable的列由JComboBox呈现。 我希望能够根据第1列中选择的值更改第2列的项目 例如,如果用户在第1列中选择Microsoft,则在第2列中可以选择ado、wpf等 可能吗?Java JTable中的依赖列,java,swing,jtable,Java,Swing,Jtable,嗨! 我有一张表格。此JTable的列由JComboBox呈现。 我希望能够根据第1列中选择的值更改第2列的项目 例如,如果用户在第1列中选择Microsoft,则在第2列中可以选择ado、wpf等 可能吗? 如果可能的话,应该听哪些事件呢?也许你可以基于此代码 table.getSelectionModel().addListSelectionListener( new ListSelectionListener() { public void valueChanged
如果可能的话,应该听哪些事件呢?也许你可以基于此代码
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int row = table.getSelectedRow();
int column = table.getSelectedColumn();
}
}
);
这是一个有趣的页面:也许您可以基于此代码
table.getSelectionModel().addListSelectionListener(
new ListSelectionListener() {
public void valueChanged(ListSelectionEvent event) {
int row = table.getSelectedRow();
int column = table.getSelectedColumn();
}
}
);
这是一个有趣的页面:只需制作自己的TableCellEditor,在调用getTableCellEditorComponent时准备JComboBox的模型。大概是这样的:
class MyEditor extends DefaultCellEditor{
public MyEditor() {
super(new JComboBox());
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JComboBox combo = (JComboBox)editorComponent;
Object column1Value = table.getValueAt(row, column-1);
Object[] options = ... create options based on other value
combo.setModel(new DefaultComboBoxModel(options));
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
只需制作自己的TableCellEditor,在调用getTableCellEditorComponent时准备JComboBox的模型。大概是这样的:
class MyEditor extends DefaultCellEditor{
public MyEditor() {
super(new JComboBox());
}
@Override
public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int row, int column) {
JComboBox combo = (JComboBox)editorComponent;
Object column1Value = table.getValueAt(row, column-1);
Object[] options = ... create options based on other value
combo.setModel(new DefaultComboBoxModel(options));
return super.getTableCellEditorComponent(table, value, isSelected, row, column);
}
}
提供了一种可能的解决方案。提供了一种可能的解决方案。您在
表格模型中使用的值是什么
一种解决方案是定义一个类,比如说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);
}
}
}
});
最后,值类的自定义单元格编辑器:
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);
}
}
公共类CategoryCellEditor扩展了DefaultCellEditor{
公共类别查询编辑器(){
super(新JComboBox());
}
静态列表所有值(列表类别){
List allValues=new ArrayList();
用于(字符串值:类别){
添加(新类别值(类别,值));
}
返回集合。不可修改列表(所有值);
}
@凌驾
公共组件getTableCellEditorComponent(JTable表、对象值、,
布尔值(选定,int行,int列){
CategoryValue CategoryValue=(CategoryValue)值;
列表类别=categoryValue.getCategories();
列出所有值=类别值。所有值(类别);
ComboBoxModel cbModel=新的默认ComboxModel(allValues.toArray());
((JComboBox)编辑器组件).setModel(cbModel);
返回super.getTableCellEditorComponent(表、类别值、,
i选定,行,列);
}
}
所有这些都是通过一个事件监听器完成的,一个很好的好处是,该事件监听器不关心如何编辑/更新表,也不关心编辑/更新来自何处
编辑以添加:或者,用一些业务对象表示表中的每一行,这些业务对象捕获为特定行所做的所有选择,并让CellEditor
从业务对象获取可用的选择(使用row
参数来getTableCellEditorComponent()
获取业务对象)。事件机制将保持不变。这样做的好处是,从业务对象中读取所选值可能比从表中刮取值更容易。您在表模型中使用什么作为值
一种解决方案是定义一个类,比如说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);
}
}
}
});
最后,值类的自定义单元格编辑器:
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);
}
}
公共类CategoryCellEditor扩展了DefaultCellEditor{
公共类别查询编辑器(){
super(新JComboBox());
}
静态列表所有值(列表类别){
List allValues=new ArrayList();
用于(字符串值:类别){
添加(新类别值(类别,值));
}
返回集合。不可修改列表(所有值);
}
@凌驾
公共组件getTableCellEditorComponent(JTable表、对象值、,
布尔值(选定,int行,int列){
CategoryValue CategoryValue=(CategoryValue)值;
列表类别=categoryValue.getCategories();
列出所有值=类别值。所有值(类别);
ComboBoxModel cbModel=新的默认ComboxModel(allValues.toArray());
((JComboBox)编辑器组件).setModel(cbModel);
返回super.getTableCellEditorComponent(表、类别值、,
i选定,行,列);
}
}
所有这些都是通过一个事件监听器完成的,一个很好的好处是,该事件监听器不关心如何编辑/更新表,也不关心编辑/更新来自何处
编辑以添加:或者,用一些业务对象表示表中的每一行,这些业务对象捕获为特定行所做的所有选择,并让CellEditor
从业务对象获取可用的选择(使用row
参数来getTableCellEditorComponent()
获取业务对象)。事件机制将保持不变。这样做的优点是,从业务对象中读取所选的值可能比刮表更容易