What is the best way to listen for changes in JTable cell values and update database accordingly?
Asked Answered
G

4

10

I'm building and app with multiple JTables and I need to detect when cell value change occurs so I can update it in the database. I tried TableModelListener and overriding tableChanged, but it fires only when I click away (click on another row) after I have edited a cell.

Any other way to do this?

Gaberdine answered 10/10, 2012 at 15:53 Comment(4)
I think that is possible to add Listener, everything depends of your XxxCellEditor, but safer way could be waiting after cell is validated on StopCellEdit (the same with MsExcell, without VBA/VBE), otherwise you have in riskMerrick
@Merrick what kind of listener? I already tried TableModelListener.Gaberdine
not to add proper listener to the JComponent that representing Editor,Merrick
If possible, I'd try and wait till setValueAt on the table model is called, personallyVidar
C
21

You can implement the CellEditorListener interface, as shown in this example. Note that JTable itself is a CellEditorListener.

It may also be convenient to terminate the edit when focus is lost, as shown here:

table.putClientProperty("terminateEditOnFocusLost", true);

More Swing client properties may be found here.

Clydeclydebank answered 10/10, 2012 at 19:20 Comment(5)
+1 ooo... I like. Too bad these properties are annoying/difficult to find documentation on.Noshow
Do you think it's a good idea to use TableModelListener and tableChanged()`?Gaberdine
Out of context, good is hard to measure. Try to cover all normal exit paths and use a UPS.Clydeclydebank
@Clydeclydebank And how about JTextArea/JTextPane? Is there an event listener similar to this, where I don't have to use DocumentListener and update the database every time a character is entered? An event that fires on "JTextArea end edit" if what I'm after.Gaberdine
You could stash a working copy of the content in java.util.Preferences, as a hedge, and clear it on database commit. VK_Enter is bound to insert-break, so you'd need another gesture.Clydeclydebank
N
5

I'm agreeing with @mKorbel - unless all your input is checkboxes and dropdowns, you're going to want to wait until the cell editing is stopped (you don't want to commit to the database every time a letter is typed in a textbox).

If the problem is that it's not committing after focus has gone to another component, add a FocusListener that stops editing the table when focus is lost on the table:

Example:

final JTable table = new JTable();
table.addFocusListener(new FocusAdapter() {
    @Override
    public void focusLost(FocusEvent e) {
        TableCellEditor tce = table.getCellEditor();
        if(tce != null)
            tce.stopCellEditing();
    }
});
Noshow answered 10/10, 2012 at 19:19 Comment(5)
Thanks, this looks promising. I'll try it out. But, what if the program is closed before focus is lost?Gaberdine
Unless it's a natural closing (not killed by the task manager or someone using System.exit in the code), I'm 90% sure the focus lost adapter will fire. If not there's also the WindowListener that listens for the window closing.Noshow
Nope, it doesn't fire. But, I stop Cell Edit on app exit :) for all tables. I used @trashgod's simpler code to stop the editng when focus is lost and I now I just can't decide if I should save all changes on exit, or use the table model listener. I'm sure both will work now, but, which answer do I choose? I used trahsgod's code to sop cell editing and your idea to stick with not commiting everytime a letter is typed in.Gaberdine
Strange - It's seems I need to be more than 90% sure about things. Good to know!Noshow
@Igor: For reference, java.util.Preferences makes a (platform-specific) best effort to record the last value put().Clydeclydebank
S
0

I use the enter key so everytime a user hit enter the cell will update.

    DefaultTableModel dtm = new DefaultTableModel(data, columnNames);
    JTable table = new JTable(dtm);

    table.addKeyListener(new KeyAdapter() {
        @Override
        public void keyPressed(KeyEvent e) {
            if (e.getKeyCode() == KeyEvent.VK_ENTER) {

                int row = table.getSelectedRow();
                int column = table.getSelectedColumn();

                // resul is the new value to insert in the DB
                String resul = table.getValueAt(row, column).toString();
                // id is the primary key of my DB
                String id = table.getValueAt(row, 0).toString();

                // update is my method to update. Update needs the id for
                // the where clausule. resul is the value that will receive
                // the cell and you need column to tell what to update.
                update(id, resul, column);

            }
        }
    });
Sontag answered 21/11, 2013 at 8:43 Comment(1)
map KyeBindings not KeyListenerMerrick
S
0

This is also handy if you want to stop the editing on an event handler from selection change or save button.

if (table.isEditing())
    table.getCellEditor().stopCellEditing();
Spencer answered 18/8, 2015 at 9:15 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.