JTable Editor Change with Live Data - java

I have a table model that is populated by live (external) data source that updates every xx seconds. The data is displayed in a JTable.
The user can override the data in the table cell through an celleditor that extends the AbstractCellEditor. If the user clicks away, the code checks to see if the new value equals the value in the table model. If it doesn't, it assumes it's an override.
The problem is, say a you click on a field, don't change the value, and external data source updates the table model in the meantime, the code thinks the user set an override using the old value rather than just cancelling the override.
What is the standard logic and implementation to do this?

How do I detect whether a user has
made a change or not?
I made a class which I call TableCellListener that listens for changes made via a cell editor. It takes a copy of the value before the cell starts editing and compares it to the value of the cell after it stops editing. It sounds like it might be what you want.
Another solution might be to check if the table is currently editing the cell before you update the TableModel in the background. Maybe you popup a dialog giving the user a chance to accept the update or cancel it.

Your table model should maintain state that indicates if a table cell was overriden on a cell-by-bell basis. If you dont do that, you will also run into the problem where a user has overriden a cell and the live data comes in and changes to the same value that the use has put in. You will then cancel that override.
You can populate this state in an overriden setValueAt(Object,int,int) method in your TableModel. This method will get called by the JTable when your AbstractCellEditor finished editing.

Related

JTable multiselect loses selection when table data changes

A JTable displays data from an array of objects. Object data changes in the background and the table is updated. When rows are selected and the table data changes the row selections are lost. It is difficult for the user to select rows for an action when the selections are frequently lost.
Is there a way to stop the deselection?
Here's what I found using the debugger. The row selection is being cleared during the call to fireTableDataChanged, which I was using to apply the updates in the table.
Apparently that method redraws the table and the selection may not be valid (as suggested by the MadProgrammer comment above). I will still be needing that feature when objects (rows) are be added or removed.
So what I must do is find a way to notify the table model to make updates to without clearing the selection. I have chosen for now to use fireTableRowsUpdated when updates are to be applied that do not require restructuring the table and fireTableDataChanged otherwise.

Changing current selection in JXTable doesn't work?

I have a JXTable where the users need to introduce data, then save it. Only the thing is, the user has to deselect the last edited cell before saving it. If they don't, the data of that cell isn't saved.
The only thing I thought of is to change the current selection automatically just before saving. This is what i tried :
table.getSelectionModel().setSelectionInterval(0, 0);
table.getColumnModel().getSelectionModel().setSelectionInterval(0, 0);
OR
table.getSelectionModel().setLeadSelectionIndex(0);
table.getColumnModel().getSelectionModel().setLeadSelectionIndex(0);
None of both seem to work yet these are the only two methods I found to do this.
Can anyone please tell me how to do this properly or propose an alternative to also let it save the data from that last cell?
I am assuming the user clicks on another component (JButton) when he wishes to save data. If you have a reference to the JXTable when that event happens you could add the following piece of code there:
if (table.isEditing()) {
table.getCellEditor().stopCellEditing();
}
The stopCellEditing() should save the state of the model and allow you to save all the contents, including the currently selected / edited cell.
EDIT: As kleopatra pointed out, the default (and better!) way to handle this is through the client property of JTable component:
table.putClientProperty("terminateEditOnFocusLost", Boolean.TRUE);
For JXTable this should already be set though, which indicates that the way your UI handling of the save functionality works does not include moving the focus away from the table. So in essence you'd be better off changing the focus when your 'save' event is being fired.

JTable erratic behavior

I have some old Java application that uses JTable to show some data and allow input as well.
JTable has 2 columns. Next to JTable, there is button that adds new row into JTable.
My problem is behavior of Tab and Enter keyboard keys and mouse clicks when you navigate JTable.
I will try to explain:
Let say there are 5 rows in JTable:
if I click with mouse on one row, sometime whole row gets highlighted, and sometime cell gets into edit mode (in addition to whole row being higlighted)
Sometime, selected row gets highlighted, but cell above or below highlighted row gets into edit mode
If I use Tab to skip from one field to another, editable field is always above highlighted row.
There are other issues as well.
Any ideas what might be wrong with it?
That sounds a bit odd. Are you fully invalidating your table and notifying listeners etc that the number of rows have changed?
In your table model, loop over all of your TableModelListeners and fire a TableModelEvent 'insert' event:
TableModelEvent event = new TableModelEvent(
modelInstance,
positionOfNewRow,
positionOfNewRow,
TableModelEvent.ALL_COLUMNS,
TableModelEvent.INSERT);
for (TableModelListener l: listeners) {
l.tableChanged(event);
}
If you can't work out the problem, it is possible to write your own behaviour for the table.
These are some useful methods:
editCellAt(int row, int column);
rowAtPoint(Point point);
columnAtPoint(Point point);
You can add your own listeners to the table to intercept events and edit cells in any way you like.
Turn off the Table cell editing. And see how it behaves. Typically this can be handled by changing the TableModel.isCellEditable() method to simply return false.
Turn it back on. Is your instance of JTable subclassed? Is it overriding editCell()? If so that's the method that will trigger an edit based on the event occurring or not. That method is turning on editing inappropriately. The implementation of that method is bad if it's overridden.
If your table isn't subclassed look for calls to editCell(). Those are probably calling it inappropriately so you can look for those calls and start setting breakpoints or log statements.

Reset old value in a JTable cell when the new one is not correct

I have a JTable to enter some numbers ina certain range. When they exceed that range, an exception occurs to show an error. Also when you enter other characters or even you enter nothing.
When those things happen, I want to get the old value back. I have thought to make a listener which warns me when a cell gets focus (I mean when the cell is opened for entering values). Then I would save that value, and if something goes wrong, I have the value ready to be entered again.
I have searched for a while but I haven't seen the way to do that listener yet. How could I do that (or in a different way)?
Table model (your subclass of AbstractTableModel) is expected to do the validation.
When JTable is updated, it performs a call to
public void setValueAt(Object aValue, int rowIndex, int columnIndex)
Validate the value there, if it does not match the range, just do not update it in your implementation of the model. After setValueAt() is called, the table re-reads the value from model (by a call to getValueAt()), so the original content gets back to the table.
http://www.java2s.com/Code/JavaAPI/javax.swing.table/implementsTableCellEditor.htm
See stopCellEditing()
From the Javadoc:
"Tells the editor to stop editing and accept any partially edited value as the value of the editor. The editor returns false if editing was not stopped; this is useful for editors that validate and can not accept invalid entries."
Here is a much better solution: Use a data model. Your model contains the values.
When the table renders, take the values from your model.
When a user edits a cell, take the current value. When the edit succeeds, put the new value into your model. If the edit fails, just refresh the cell: The renderer will take the unmodified value from your model and you're done.

JTable that can save to a file

Does anyone know of a JTable based Swing component OR code example that can save to a file? i.e: provides a menu item or button that when clicked on prompts the user for a file location and saves the table's contents to a file (CSV, XLS, TXT, or whatever).
The easy part is looping through the rows and saving to a file. But there also needs to be a UI component ON the table itself that allows the user to initiate the save.
Write your own. All you do is use the table.getModel().getValueAt(...) method and loop through the rows and columns and then write the data to a file.
I have implemented this using the following approach:
Create an Action implementation: DelimitedExportAction. I typically add this action to a JToolBar, JMenuBar or JPopupMenu.
Expose a method void registerTable(JTable tbl). Internally this method adds a FocusListener to the JTable. When a given JTable gains focus set the tableToExport instance variable and enable the action.
When the actionPerformed(ActionEvent) method is called, invoke your export logic if tableToExport != null.
Rather than iterate over the TableModel I recommend iterating over the JTable, and for each row calling getValueAt(int, int) on the underlying TableModel, remembering to convert between view and model row / column indices. This is more intuitive to the end user as it means any sorting and filtering applied to the JTable is preserved during the export. (In my implementation I actually offer users the choice of exporting all data or visible data.)
Define a DelimitedExportFormatter whose role is to convert each object returned by getValueAt(int, int) to a String. Similar to when providing renderers to a JTable this class should permit you to provide a Format for a given Class or specific column, whereby a column specific format takes precedence. The default format applied to all other values should be: value == null ? "" : value.toString().
I allow the action to be configured in different modes (which also governs the action's icon):
Export to file: Launches a file chooser dialog allowing user to specify save destination.
Export to Excel: Saves the exported data as a temporary file and opens it within Excel.
Configurable export: Launches a dialog whereby the user can specify: row delimiter, field delimiter, columns to export, rows to export (all, visible, selected), save destination (Excel / File).
I'm afraid I can't provide the code as it is proprietary but hopefully this will put you on the right track. Good luck!
I recently created a very simple tutorial that exports data from JTable into excel file, using Tab-Separated Values(TSV) format. The application provides an Export button, which then triggers a dialog box (JFileChooser) to assist the user in specifying the file location/destination. I hope this helps somehow.
https://sites.google.com/site/teachmemrxymon/java/export-records-from-jtable-to-ms-excel
I don't know of any JTable-like Swing component that fulfills this exact need.
However, where would you expect the button to be placed on the table? In my opinion you would be better served by either adding the JTable to a JScrollPane and putting your "save" button on the JScrollPane or adding the JScrollPane to a JPanel and putting the "save" button on the JPanel. I don't see the logic behind having a button on the JTable itself.
If you want a menu item, you'd probably want to create the menubar and add the JTable to whatever container is holding the menubar. There's still no adding of a button to the table itself, mind you, but it would be the same thing visually.

Categories

Resources