JTable stop cell editing without user click
Asked Answered
O

1

6

I'm trying to solve a strange problem with my program. This program creates a series of GUI's and JTables that give a user the ability to generate an XML file. One of these tables is for creating the "statements". I won't get into detail as far as that except to say that the data is stored in multiple 2D arrays which are in turn stored in a hash map.

Here is what happens. When a user enters the Statement screen a JTable is generated using the contents from the 2D array. This data populates the cell's which the user is able to modify. One of these cells (and the most important) is the amount. The amounts they set for the rows much match another amount from another class.

At the bottom of the table is a "finished" button. When the user clicks this button the logic will check to see if the money amounts match. If they do then the program will update the 2D array with any changed values and dispose of the JTable.

My problem is that once a user updates a cell and clicks "finished" the last updates made do not work. Essentially the user must first click somewhere else in the table and THEN hit finished. I would like this action to happen automatically so that when the user clicks "finished" cell editing is stopped. Here is the code for the finished button:

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

                }



            }

        });

I think my problem is with this line:

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

This only seems to work once the user has clicked another area of the table after editing a cell.

I appreciate the help!

Ochlocracy answered 15/7, 2016 at 13:49 Comment(2)
correct me if, maybe am I worng, but code posted talking nothing about XxxEditor, just to take a value from row(s), editor doesn't has to do with ActionListener from JButtons, maybe some missinterpretations in your questionKuth
I'm not sure what your talking about mKorbel, sorry if my question is hard to understand. This is just a simple JTable with a "finished" button at the bottom. When the user clicks finished all the cell data will be saved to a 2D array. This works just fine, the problem is simply if the user doesn't remove focus on the last cell they have edited the data they changed will not be reflected in the array value. So if they click a cell to change value "A" to "B" and don't lose focus the array will save "A"..Ochlocracy
P
20

My problem is that once a user updates a cell and clicks "finished" the last updates made do not work.

Check out Table Stop Editing for two approaches:

You can either:

Add code to the ActionListener:

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

or set a property on the table:

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

Edit:

When the user clicks finished all the cell data will be saved to a 2D array.

Why? All the data is already stored in the TableModel.

In any case you need to stop editing BEFORE you attempt to copy data from the TableModel to the Array.

Purple answered 15/7, 2016 at 14:59 Comment(6)
Hello Camickr. In the example I'm trying to demonstrate the cell has not lost focus. Assuming a user clicks the cell to edit and then without clicking any other cell or "enter" they click finished. Now, the focus on the cell has not been lost. Technically they never left the "edit mode" of the cell if you will. Now it may be that I need to instruct the users that they MUST press the enter key before clicking "finished" but I was hoping to force the cell to lose focus if they click enter.Ochlocracy
@jesric1029, but I was hoping to force the cell to lose focus if they click enter. Well the cell will aways loses focus when you click on the button since only one component can have focus at a time. My answer shows you how to stop editing on the cell so that the data is entered into the TableModel. It gives you two different ways to do this. See edit.Purple
I tried both of those solutions. Apparently the cell does not lose focus before the button listener runs. I can tell because if I enter an incorrect value into the cell that causes the amounts not to match and press "finished" without doing anything else the error will not generate. If I press enter after typing or click another row after typing the incorrect amount however, the message will display.. It's minor for users to have to press enter but it will make it easier not to have people confused.Ochlocracy
Apparently the cell does not lose focus before the button listener runs. - I know, I already stated that. That is why you need to stop editing as the first statement in the ActionListener. if I enter an incorrect value - your question is about saving data to the TableModel when a button is clicked. You have been given two solutions for this. I have no idea what your editing code is doing since it was not part of the question. If you still have problems then post a proper SSCCE showing how you have implemented the suggestions.Purple
It's okay. I think I understand why it doesn't work I'm just having trouble explaining it. Anyway your solution is correct even though I'm still having problems so I'll mark as accepted. Thanks for your help!Ochlocracy
@jesric1029, I'm just having trouble explaining it. - which is why you should ALWAYS post a SSCCE with your question so we can execute the code to see exactly what is happening even if your explanation is not clear. A SSCCE is simple to create. You create a frame with a JTable and a JButton. Get the simple code to work first before trying to make your real application work.Purple

© 2022 - 2024 — McMap. All rights reserved.