当前位置: 首页 > 知识库问答 >
问题:

在单击按钮时使用自定义TableModel使特定行的isCellEditable为true

魏俊茂
2023-03-14

我有一张像上面这样的桌子。最初,除了按钮列之外,所有的单元格都是不可编辑的。我已经使用自定义TableModel创建了表。自定义TableModel中的Myiscelleditable如下所示:

public boolean isCellEditable(int rowIndex, int columnIndex) { 
    //System.out.println("isCellEditable: " + rowIndex + " " + columnIndex);
    if(getColumnClass(columnIndex) == JButton.class)
        return true;
    else
        return false;
}

但当我单击每一行的Edit按钮时,就会弹出一个JDialog(通过在该对话框中只使用一行构造一个JTable)我可以更新这个JDialog表中的单元格值。然后在该行的相应单元格中更新它们。

只有在iscelleditable返回true的情况下,我在此处更新后才成功更新了主表的行。但这不应该发生。只有在单击时,才可以将行的iscelleditable更改为可编辑和更新,然后使其不可编辑。

共有1个答案

吉毅
2023-03-14

补充一下我对这个问题的评论:

不需要调整完整模型的可编辑性:创建另一个模型,由原始模型的过滤行(按列)填充,使其可编辑,并在提交时让其将更改的值写回原始模型

用一点代码:

public static class ButtonDialogEditor extends AbstractCellEditor 
     implements TableCellEditor {
    // the columns to present for editing, in model coordinates
    public final int lastColumn;
    public final int firstColumn;
    // the row to present for editing, in model coordinates
    private int row;

    private DefaultTableModel model;
    private JDialog dialog;
    private boolean committed;
    private JButton editingComponent;

    public ButtonDialogEditor(int firstColumn, int lastColumn) {
       this.firstColumn = firstColumn;
       this.lastColumn = lastColumn;

       model = new DefaultTableModel(1, lastColumn - firstColumn + 1);
       JTable table = new JTable(model);
       table.putClientProperty("terminateEditOnFocusLost",true);
       dialog = new JDialog();
       dialog.setModal(true);
       dialog.add(new JScrollPane(table));
       dialog.add(new JButton(createOkAction()), BorderLayout.SOUTH);
       dialog.pack();
       editingComponent = new JButton(createShowDialogAction());
    }

    /**
     * Returns the cell value at column. Note that column
     * is in the model coordinate system of the source model.
     */
    public Object getValueAt(int column) {
        return model.getValueAt(0, column - firstColumn);
    }

    /**
     * Returns the row index of the edited row in 
     * model coordinates of the source table.
     */
    public int getModelRow() {
        return row;
    }

    /**
     * Creates and returns the action used for 
     * the editing component button.
     * 
     * Implemented to show the modal dialog and fire 
     * editingSotpped/canceled depending on the committed
     * flag
     */
    private Action createShowDialogAction() {
        Action action = new AbstractAction() {

            @Override
            public void actionPerformed(ActionEvent e) {
                // reset committed
                committed = false;
                dialog.setVisible(true);
                if (committed) {
                    fireEditingStopped();
                } else {
                    fireEditingCanceled();
                }
            }
        };
        return action;
    }

    /**
     * Creates and returns the action used for the dialog's
     * OK button.
     * 
     * Implemented to hide the dialog and set the
     * committed flag to true.
     */
    private Action createOkAction() {
        Action action = new AbstractAction("OK") {
            @Override
            public void actionPerformed(ActionEvent e) {
                dialog.setVisible(false);
                committed = true;
            }
        };
        return action;
    }

    @Override
    public Component getTableCellEditorComponent(JTable table,
            Object value, boolean isSelected, int row, int column) {
        editingComponent.setText(value != null ? value.toString() : "");
        prepareDialog(table, row);
        return editingComponent;
    }

    /**
     * Update internal state to the row to edit. 
     */
    private void prepareDialog(JTable table, int row) {
        this.row = table.convertRowIndexToModel(row);
        for (int i = firstColumn; i <= lastColumn; i++) {
            model.setValueAt(table.getModel().getValueAt(this.row, i), 0, i - firstColumn);
        }
    }

    /**
     * Implemented to return the original value as 
     * given in the 
     */
    @Override
    public Object getCellEditorValue() {
        return editingComponent.getText();
    }

}

public static class ButtonRenderer implements TableCellRenderer {

    JButton button = new JButton();
    @Override
    public Component getTableCellRendererComponent(JTable table,
            Object value, boolean isSelected, boolean hasFocus, int row,
            int column) {
        button.setText(value != null ? value.toString() : "");
        return button;
    }
}

// example usage
// source model is not editable except for the button column
final DefaultTableModel model = new DefaultTableModel(0, 3) {
    @Override
    public boolean isCellEditable(int row, int column) {
        return column == 0;
    }
};
for (int i = 0; i < 20; i++) {
    model.addRow(new Object[] {"Edit", i});
}
JTable table = new JTable(model);
table.getColumnModel().getColumn(0).setCellRenderer(new ButtonRenderer());
final ButtonDialogEditor cellEditor = new ButtonDialogEditor(1, model.getColumnCount() - 1);
// custom editor listener which writes back the edited values
// to the model on editingStopped.
CellEditorListener l = new CellEditorListener() {

    @Override
    public void editingStopped(ChangeEvent e) {
        for (int i = cellEditor.firstColumn; i <= cellEditor.lastColumn; i++) {
            model.setValueAt(cellEditor.getValueAt(i), cellEditor.getModelRow(), i);
        }
    }

    @Override
    public void editingCanceled(ChangeEvent e) {
        // nothing to do
    }
};
cellEditor.addCellEditorListener(l);
table.getColumnModel().getColumn(0).setCellEditor(
        cellEditor);
 类似资料:
  • 在我的应用程序中,我有一个通知要显示。 比方说,当显示通知时,我想按“是”进入活动并隐藏通知,按“否”什么都不做只是隐藏通知。 我尝试了这段代码,但是onclick不是onclckpendingent,我不能做任何我想做的事情。 我怎么能这样做?

  • 因此,当我试图在程序中实现JTable时,我一直在阅读Java的“如何使用表”。我想要的是从数据库中获取一个字符串值列表,然后按列名和行名对它们进行排序。现在我知道没有像列那样的默认行标头,所以我通过将我的第一列设置为“行标头”来避开这个问题。因此,我决定为我的Jtable创建一个自定义表模型,以便正确地对数据进行排序(数据存储在字符串向量的向量中&列/行名分别作为字符串向量),但我遇到的只是问题

  • 我对全日历有问题。我正在使用周视图(DefaultView:“Basic week”)和工具栏按钮“Today”、“Prev”、“Next”。当我点击“今天”按钮时,日历就会返回到当前的一周,但日期选择不会改变。我希望“日历”导航到“当前周”并在“日历”上选择“今天日期”。但我有麻烦重新定义‘今天’按钮点击事件。 代码示例:https://plnkr.co/edit/dv9yiq1cdjxffts

  • 问题内容: 我想问一个与这个问题相同的问题,但使用SWT:是否有一种方法可以制作带有您自己的按钮图形的按钮,而不仅仅是按钮内的图像?如果不是,这是在Java中创建自定义按钮的另一种方法吗? 问题答案: public class ImageButton extends Canvas { private int mouse = 0; private boolean hit = false;

  • 问题内容: 如何在flutter中创建这样的自定义单选按钮组 问题答案: 这是完整的代码 To use :

  • 问题内容: 我正在尝试在Java GUI上实现JTable,该JTable可以使用文件中的值填充自身,并允许用户对各种单元格进行修改。由于我在Netbeans IDE中使用GUI编辑器,因此我的第一个直觉是将JTable从面板添加到表单中。但是,我很快意识到我不能在表中添加超过100行(对于我的应用程序,我需要大约500行以上)。另外,在寻找解决方案时,我注意到很多人说使用Custom Table