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

我希望能够在一个带有JButton的单元格中有一个JPanel,它在单击时可以完成一些工作。

我找了关于Cell Editors的howtos,但所有的例子都谈到用另一个组件替换单元格(例如用JTextField等替换int)我的情况有点不同:

我有以下ADT

class MyClass { public String title; public String url; public String path; public int annotations; } 

我创建了一个自定义表格单元格模型,该模型有1列,该列的类是MyClass。 然后我为该类创建了一个单元格渲染器,它返回一个JPanel,如下所示:

MyClass Cell Renderer

如您所见,JPanel包含一个按钮。 我希望这个按钮在点击时启动JFrame。 有任何想法吗?

如果您将建议Cell Editor,请更具体地说明如何操作。 如果可能,请提供一些伪代码。

谢谢。

PS我很确定这个问题的标题需要一些工作。 ;)

在编码.mof的回复后 ,我终于做了我想要的。 但是,我想要一个更完整的答案来解决这个问题,所以我会自己提供一个。

因此,Cell Renderers只是绘制组件并且不允许其中的任何交互。 细胞编辑的确如此。

最初,JTable中的所有单元格都是由已注册的渲染器返回的组件。 但是,选择单元格时,此组件将被编辑器返回的组件替换。 这两个实际上可以是不同的组件! 我非常确定你可以利用这个并制作一些时髦的细胞:P

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

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

 class MyClassTableModel extends DefaultTableModel { List data; public MyClassTableModel(List 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; } } 

现在,我们创建一个将在Renderer和Editor之间共享的组件:

 class MyClassCellComponent extends JPanel() { MyClass myClass; public MyClassCellComponent() { // initialize components (labels, buttons, etc.) // add action listeners } public void updateData(MyClass myClass, boolean isSelected, JTable table) { this.myClass = myClass; // update buttons, labels etc. accordingly } } 

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

我们完成了!

PS我很确定我们可以将Renderer和Editor组合成一个扩展AbstractCellEditor并实现TableCellRenderer的类,但我不确定性能。

 public class MyTableCellEditor extends AbstractCellEditor implements TableCellEditor { JComponent pan = new JPanel(); public MyTableCellEditor () { pan.add(btn); // add all elments you need to your panel btn.addActionListener( /* the listener which will handle the events */ ); } public Component getTableCellEditorComponent(JTable table, Object value, boolean isSelected, int rowIndex, int vColIndex) { btn.setText( /* according to row or whatever*/ ); // set all elemnts of you panel to the according values // or add dynamically an action listener return pan; } public Object getCellEditorValue() { return new Void(); } } 

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

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