JTable 中的从属列

发布于 2024-08-04 21:59:35 字数 177 浏览 6 评论 0 原文

嗨! 我有一个 JTable。此 JTable 的列由 JComboBox 呈现。 我希望能够根据第 1 列中选择的值更改第 2 列的项目。

例如,如果用户在第 1 列中选择 Microsoft,那么在第 2 列中他/她可以选择 ado、wpf 等。

是吗?可能的 ? 如果可能的话,应该监听哪些事件呢?

Hie!
I have a JTable. Columns of this JTable are rendered by JComboBox.
I would like to be able to change items of column 2 on the basis of values selected in column 1.

For example if the user selects Microsoft in column 1, then in column 2 he/she can select ado, wpf, etc.

Is it possible ?
If it is possible, than which events should be listened to do it ?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

紫竹語嫣☆ 2024-08-11 21:59:35

组合框表格编辑器提供了一种可能的解决方案为了这。

The Combo Box Table Editor provides one possible solution for this.

讽刺将军 2024-08-11 21:59:35

也许你可以基于这段代码;

table.getSelectionModel().addListSelectionListener(
    new ListSelectionListener() {
        public void valueChanged(ListSelectionEvent event) {
            int row = table.getSelectedRow();
            int column = table.getSelectedColumn();     
        }
    }
);

这是一个有趣的页面:点击

Maybe you can base you on this code;

table.getSelectionModel().addListSelectionListener(
    new ListSelectionListener() {
        public void valueChanged(ListSelectionEvent event) {
            int row = table.getSelectedRow();
            int column = table.getSelectedColumn();     
        }
    }
);

This is an intresting page: click

奢华的一滴泪 2024-08-11 21:59:35

只需创建您自己的 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);
    }

}

Just make your own TableCellEditor that preps the JComboBox's model on the call to getTableCellEditorComponent. Something like this:

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);
    }

}
赠佳期 2024-08-11 21:59:35

您在 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>。)

接下来是值类:

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 从业务对象(使用 getTableCellEditorComponent()row 参数来获取业务对象)。事件机制将保持不变。这样做的优点是,从业务对象中读取所选值可能比抓取表更容易。

What are you using as values in your TableModel?

One solution would be to define a class, say CategoryValue, that represents a list of possible items and a selected item, and use that; then listen for TableModelEvents and when a value in column 0 changes, set the corresponding value in column 1. A simple example is below.

First, the 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);
      }
    }
  }
});

(Implementing getChildCategories(String) depends on where your data is coming from, but it could be as simple as a Map<String, List<String>>.)

Next, the value class:

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;
  }
}

Finally, a custom cell editor for the value class:

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);
  }
}

All done with one event listener, and a nice bonus is that that event listener doesn't care how the table is edited/updated, or where the edits/updates come from.


Edited to add: Alternatively, represent each row of the table with some business object that captures all the choices made for a particular row, and have the CellEditor get the available choices from the business object (using the row argument to getTableCellEditorComponent() to get the business object). The event mechanism would remain the same. This has the advantage that it's probably easier to read the selected values from the business object than to scrape the table.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文