我希望能够在一个带有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,如下所示:
如您所见,JPanel包含一个按钮。我希望这个按钮在点击时启动JFrame。有什么想法吗?
如果您建议使用Cell Editor,请详细说明如何操作。如果可能,请提供一些伪代码。
谢谢。
P.S。我很确定这个问题的标题需要一些工作。 ;)
答案 0 :(得分:7)
在coding.mof's reply之后,我终于做了我想要的。但是,我想对这个问题有一个更完整的答案,所以我会自己提供一个。
因此,Cell Renderers只是绘制组件并且不允许其中的任何交互。虽然细胞编辑有。
最初,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; }
}
现在,我们创建一个将在渲染器和编辑器之间共享的组件:
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());
我们已经完成了!
P.S。我很确定我们可以将Renderer和Editor组合成一个扩展AbstractCellEditor并实现TableCellRenderer的类,但我不确定性能。
答案 1 :(得分:5)
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。
答案 2 :(得分:0)
您可以创建一个包含多个列的表,然后您可以添加一个单独的列来包含您的按钮。 Table Button Column类允许您轻松完成此操作。