Java JTable:单元格中自定义面板中的按钮

Java JTable:单元格中自定义面板中的按钮,java,jtable,jpanel,jbutton,Java,Jtable,Jpanel,Jbutton,我希望能够在一个单元格中有一个JPanel,该单元格中有一个JButton,单击该按钮时可以执行一些操作 我查找了有关单元格编辑器的说明,但所有示例都谈到用另一个组件替换单元格(例如,用JTextField替换int等)。我的情况略有不同: 我有以下ADT class MyClass { public String title; public String url; public String path; public int annotations; } 我创建了一个自定义表

我希望能够在一个单元格中有一个JPanel,该单元格中有一个JButton,单击该按钮时可以执行一些操作

我查找了有关单元格编辑器的说明,但所有示例都谈到用另一个组件替换单元格(例如,用JTextField替换int等)。我的情况略有不同:

我有以下ADT

class MyClass {
  public String title;
  public String url;
  public String path;
  public int annotations;
}
我创建了一个自定义表格单元模型,它有一列,该列的类是MyClass。然后,我为该类创建了一个单元呈现器,它返回一个JPanel,如下所示:

如您所见,JPanel包含一个按钮。我希望此按钮在单击时启动JFrame。有什么想法吗

如果您建议使用Cell Editor,请详细说明如何使用。如果可能,提供一些伪代码

多谢各位

另外,我很确定这个问题的标题需要一些修改

因此,在监听器中,您必须检查表的选择,以便能够以不同的方式对每一行进行响应。 如果希望将所有元素保留在一列中,可以将JButton替换为包含所有组件的面板。然后,JTable将所有事件转发给该JPanel。

之后,我终于完成了我想要的。然而,我想对这个问题有一个更完整的答案,所以我将自己提供一个

因此,单元渲染器只绘制组件,不允许在组件内进行任何交互。而单元格编辑器可以

最初,JTable中的所有单元格都是由注册的呈现程序返回的组件。但是,当选定单元格时,该组件将替换为编辑器返回的组件。这两者实际上可以是不同的组件!我很确定你可以利用这一点,制作一些时髦的细胞:P

无论如何,在本例中,渲染器和编辑器都显示相同的组件,因此我们将创建一个供两者使用的组件

首先,我们需要创建一个返回ADT的TableModel:

class MyClassTableModel extends DefaultTableModel {
  List<MyClass> data;

  public MyClassTableModel(List<MyClass> data) {
    this.data = data;
  }

  public Class<?> getColumnClass(int columnIndex) { return MyClass.class; }
  public int getColumnCount() { return 1; }
  public String getColumnName(int columnIndex) { return "MyClass"; }
  public int getRowCount() { return (data == null) ? 0 : data.size(); }
  public Object getValueAt(int rowIndex, int columnIndex) { return data.get(rowIndex); }
  public boolean isCellEditable(int rowIndex, int columnIndex) { return true; }
}
isSelected和table参数用于渲染面板的背景,是可选的。以下是渲染器如何使用我们的组件:

class MyClassCellRenderer implements TableCellRenderer {
  MyClassCellComponent panel;

  public MyClassCellRenderer() {
    panel = new MyClassCellComponent();
  }

  public Component getTableCellRendererComponent(JTable table, Object value,        boolean isSelected, boolean hasFocus, int row, int column) {
    MyClass myClass = (MyClass)value;
    panel.updateData(myClass, isSelected, table);
    return panel;
  }
}
以下是编辑器如何使用它:

class MyClassCellEditor extends AbstractCellEditor {
  MyClassCellComponent panel;
  public MyClassCellEditor() {
    panel = new MyClassCellComponent();
  }
  public Component getTableCellEditorComponent(JTable table, Object value,      boolean isSelected, int row, int column) {
    MyClass myClass = (MyClass)value;
    panel.updateData(myClass, true, table);
    return panel;
  }
  public Object getCellEditorValue() {
    return null;
  }
}
就这些。现在,我们可以简单地创建一个JTable,如下所示:

JTable myClassTable = new JTable(new MyClassTableModel());
myClassTable.setDefaultRenderer(MyClass.class, new MyClassCellRenderer());
myClassTable.setDefaultEditor(MyClass.class, new MyClassCellEditor());
我们完了


另外,我很确定我们可以将渲染器和编辑器组合成一个类扩展AbstractCellEditor并实现TableCellRenderer,但我不确定性能。

您可以创建一个包含多个列的表,然后可以添加一个单独的列来包含按钮。该类允许您轻松完成此操作。

这是否意味着我不再需要我的CellRenderer?我只是把它做成一个单元格编辑器?不。如果你这样做,一个空白单元格就会被渲染。JTable在内部仅将渲染器用于显示数据。但是如果你点击一个单元格,它将变成可编辑的,由celleditor提供的组件将被显示。是的,我在问过你之后就试过了,事实上就是这样。非常感谢。我希望避免这种情况,因为我希望能够按照自己的意愿(如屏幕截图所示)放置我的组件,而不是一个挨着另一个。这样,拥有两个列可能会更容易。一个用于数据,一个用于按钮。可以从表中删除垂直线,使其看起来仍然像一列。
class MyClassCellEditor extends AbstractCellEditor {
  MyClassCellComponent panel;
  public MyClassCellEditor() {
    panel = new MyClassCellComponent();
  }
  public Component getTableCellEditorComponent(JTable table, Object value,      boolean isSelected, int row, int column) {
    MyClass myClass = (MyClass)value;
    panel.updateData(myClass, true, table);
    return panel;
  }
  public Object getCellEditorValue() {
    return null;
  }
}
JTable myClassTable = new JTable(new MyClassTableModel());
myClassTable.setDefaultRenderer(MyClass.class, new MyClassCellRenderer());
myClassTable.setDefaultEditor(MyClass.class, new MyClassCellEditor());