JTable 无需用户单击即可停止单元格编辑

Posted

技术标签:

【中文标题】JTable 无需用户单击即可停止单元格编辑【英文标题】:JTable stop cell editing without user click 【发布时间】:2016-11-18 18:18:31 【问题描述】:

我正在尝试解决我的程序的一个奇怪问题。该程序创建一系列 GUI 和 JTable,使用户能够生成 XML 文件。这些表之一用于创建“语句”。除了说数据存储在多个二维数组中,这些数组又存储在哈希图中,我不会详细说明。

这就是发生的事情。当用户进入 Statement 屏幕时,会使用 2D 数组中的内容生成 JTable。该数据填充用户能够修改的单元格。这些单元之一(也是最重要的)是数量。他们为行设置的数量与另一个类的另一个数量非常匹配。

表格底部是一个“完成”按钮。当用户单击此按钮时,逻辑将检查金额是否匹配。如果他们这样做了,那么程序将使用任何更改的值更新 2D 数组并处理 JTable。

我的问题是,一旦用户更新单元格并单击“完成”,最后所做的更新将不起作用。本质上,用户必须首先单击表中的其他位置,然后点击完成。我希望此操作自动发生,以便当用户单击“完成”单元格编辑时停止。这是完成按钮的代码:

finishedButton.addActionListener(new ActionListener()

            public void actionPerformed(ActionEvent ae)

                //Creates another table model for the finished button logic. 
                DefaultTableModel dm = (DefaultTableModel)StatementGUI.tbl.getModel();

                //Gets the total number of table rows. 
                int rows = dm.getRowCount();

                //Creates a variable to store the statement transaction total. 
                double statementTransactionTotal=0;

                //For each row in the table. 
                for(int i = 0; i < dm.getRowCount(); i++)

                    //Gets the total of all transactions in the table. 
                    String currentTotal = tbl.getValueAt(i, 3).toString();
                    Double currentTotalDouble = Double.parseDouble(currentTotal);
                    statementTransactionTotal=statementTransactionTotal+currentTotalDouble;

                

                //Creates a decimal format and applies the statement total. 
                DecimalFormat df = new DecimalFormat("0.00");
                String currentTotalDF = df.format(statementTransactionTotal);

                //Stops editing on the table so that the data can be used. 
                if(null != tbl.getCellEditor())
                    tbl.getCellEditor().stopCellEditing();
                

                //If the statement total matches the transaction total..
                if(currentTotalDF.matches(ClearedMainGUI.currentTransactionAmount))

                    //For each row in the table..
                    for(int i = 0; i < dm.getRowCount(); i++)

                    //Will replace the hash/array value with the table value. 
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][0]=tbl.getValueAt(i, 0).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][1]=tbl.getValueAt(i, 1).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][2]=tbl.getValueAt(i, 2).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][3]=tbl.getValueAt(i, 3).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][4]=tbl.getValueAt(i, 4).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][5]=tbl.getValueAt(i, 5).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][6]=tbl.getValueAt(i, 6).toString();
                    ClearedMainGUI.Transactions.get(ClearedMainGUI.selectedRow)[i][7]=tbl.getValueAt(i, 7).toString();

                    


                    //For each row in the table..
                    for(int i = rows - 1; i >=0; i--)

                        //Removes the current row so the table will be empty next time. 
                        dm.removeRow(i);

                    

                    //Removes the frame and goes back to the previous GUI. 
                    frame.dispose();

                //If the statement total and transaction total do not match..
                else

                    JOptionPane.showMessageDialog(null, "The statement total entered: $"+statementTransactionTotal+" " +
                            "does not match the transaction total of: $"+ClearedMainGUI.currentTransactionAmount);                  

                



            

        );

我认为我的问题在于这一行:

if(null != tbl.getCellEditor())
                    tbl.getCellEditor().stopCellEditing();
                

这似乎只有在用户在编辑单元格后单击表格的另一个区域后才有效。

感谢您的帮助!

【问题讨论】:

纠正我,如果,也许我穿坏了,但发布的代码没有谈论 XxxEditor,只是为了从行中获取一个值,编辑器与 JButtons 中的 ActionListener 无关,也许是一些您的问题中的误解 我不确定你在说什么 mKorbel,如果我的问题难以理解,我很抱歉。这只是一个简单的 JTable,底部有一个“完成”按钮。当用户单击完成时,所有单元格数据将保存到二维数组中。这工作得很好,问题很简单,如果用户没有将焦点移到他们编辑的最后一个单元格上,他们更改的数据将不会反映在数组值中。因此,如果他们单击一个单元格以将值“A”更改为“B”并且不失去焦点,则数组将保存“A”.. 【参考方案1】:

我的问题是,一旦用户更新单元格并单击“完成”,最后所做的更新将不起作用。

查看Table Stop Editing 了解两种方法:

您可以:

将代码添加到 ActionListener:

if (table.isEditing())
     table.getCellEditor().stopCellEditing();

或在桌子上设置一个属性:

JTable table = new JTable(...);
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);

编辑:

当用户点击完成后,所有的单元格数据将被保存到一个二维数组中。

为什么?所有数据都已存储在 TableModel 中。

在任何情况下,您都需要在尝试将数据从 TableModel 复制到数组之前停止编辑。

【讨论】:

你好 Camickr。在示例中,我试图证明单元格没有失去焦点。假设用户单击要编辑的单元格,然后没有单击任何其他单元格或“输入”,他们单击完成。现在,对细胞的关注并没有失去。从技术上讲,如果您愿意,他们永远不会离开单元格的“编辑模式”。现在可能是我需要指示用户他们必须在点击“完成”之前按回车键,但我希望在他们点击回车时强制单元格失去焦点。 @jesric1029, but I was hoping to force the cell to lose focus if they click enter. 当您单击按钮时,单元格将失去焦点,因为一次只能有一个组件具有焦点。我的回答向您展示了如何停止对单元格进行编辑,以便将数据输入到 TableModel 中。它为您提供了两种不同的方法来做到这一点。见编辑。 我尝试了这两种解决方案。显然,在按钮侦听器运行之前,单元格不会失去焦点。我可以知道,因为如果我在单元格中输入了一个不正确的值,导致金额不匹配并按“完成”而不做任何其他事情,则不会产生错误。但是,如果我在输入后按 Enter 键或在输入不正确的金额后单击另一行,则会显示消息。用户必须按 Enter 键的情况很小,但这样更容易让人不感到困惑。 Apparently the cell does not lose focus before the button listener runs. - 我知道,我已经说过了。这就是为什么您需要停止编辑作为 ActionListener 中的第一条语句。 if I enter an incorrect value - 您的问题是关于单击按钮时将数据保存到 TableModel 的问题。为此,您得到了两种解决方案。我不知道您的编辑代码在做什么,因为它不是问题的一部分。如果您仍然有问题,请发布正确的SSCCE,说明您是如何实施这些建议的。 没关系。我想我明白为什么它不起作用我只是很难解释它。无论如何,即使我仍然遇到问题,您的解决方案也是正确的,所以我会标记为已接受。感谢您的帮助!

以上是关于JTable 无需用户单击即可停止单元格编辑的主要内容,如果未能解决你的问题,请参考以下文章

使用日期类型更新 JTable 单元格

找到 JTable 单元格并绘制它

JTable:单击按钮时更改单元格背景

无需单击目标单元格即可自动激活宏

如何使用自定义 JTable 单元格编辑器和单元格渲染器

如何使 JTable 单元格不可编辑但应该能够选择和复制当前单元格中的值