Whenever there is a lostFocus inside a JTable, i need to capture the existing cell's row and column.
However, the condition below is always false because the source is always either a JTextField or a JComboBox.
public void focusLost(FocusEvent e) {
int row, col;
Object source = e.getSource();
if(((Component) source).getParent() instanceof JTable_Ext){ //<-- always false
table = (JTable_Ext) ((Component) source).getParent();
row = table.getSelectedRow();
col = table.getSelectedColumn();
}
To mitigate the above, i remember the row and col during FocusGained (as class level variable). The problem is, if the user click very fast all over the place within the JTable, somehow the row and column information will be out of sync.
Is there a way to get the Row and Col during FocusLost? if not, is there a better way of doing this?
Well, there is the oppositeComponent. The weird thing is, if this listener is attached to the table, the documentation tells that the table should be the "source" component (because it is a FocusLost event and the component that lost the focus is the table itself).
http://download.oracle.com/javase/1.4.2/docs/api/java/awt/event/FocusEvent.html#getOppositeComponent%28%29
Could you just keep a record of row & column using
table.getSelectionModel().addListSelectionListener(...);
table.getColumnModel().getSelectionModel().addListSelectionListener(...);
So every time the use clicks update it, not just on focus events?
If you just want to save the data that was entered in the cell (without hitting return), then you don't need to do anything. The updated information is contained within TableModel of the JTable.
Otherwise you can take a look at .tableChanged() and the associated TableModelEvent, which gives you the last row/column modified. You could keep a variable that is always updated to the latest event row/column. I guess that if you change a cell number without hitting return, it nonetheless registers as an event.
However, the condition below is always false because the source is always either a JTextField or a JComboBox.
This implies that the focusLost event is being generated when you begin editing a cell. So the question is why are you doing this? I think you need to state your actual requirement, because you attempted solution does not seem appropriate.
Related
I want to hide data of a column of Jtable, but not hide the column view,just its data.
The column contain data about profit and the customer doesn't want to show the profit but in my code I use the values of this column and get it when the user select specified row.
How do I achieve the customer need and still be able to get the values of this column when selecting it after hiding its data(displaying column as empty but still has its values)?
You need to remove the TableColumn from the TableColumnModel of the JTable. For example:
table.removeColumn( table.getColumn(...) );
Now the column will not display in the table, but the data is still available in the TableModel. to access the data you use:
table.getModel().getValueAt(...);
You could try a subclassing DefaultTableCellRenderer, and call setCellRenderer. When the relevant column number is passed to getTableCellRendererComponent, return a blank JLabel, otherwise call the default super.getTableCellRendererComponent.
This should mean the column is still visible, but each cell will be blank.
If you want to display the data when a row is selected, you will need add a listener to the selection model (from getSelectionModel) to store the selected row in a variable, and call a repaint. You can then use this value in your CellRenderer.
Why don't you just let the dataModel control what is shown? I'm assuming you are using a tableModel.
All you have to do is change the getValueAt(..) method so that it does not return a value for the column you do not want to show. Make sure that getColumnCount() method is reduced by one as well.
I have JTable and rows in it. By default first row is selected and focus is in it. How can I deselect first row and change focus to somewhere else that .addListener(new RowSetListener() will work in first row too.
I already try:
tableZaposlenciView1.setRowSelectionAllowed(true);
//tableZaposlenciView1.getSelectionModel().clearSelection();
//tableZaposlenciView1.setColumnSelectionInterval(0,0);
//tableZaposlenciView1.setRowSelectionInterval(false,false);
tableZaposlenciView1.changeSelection(0,0,false,false);
tableZaposlenciView1.requestFocus();
but it is not working.
Have a look at JTable's changeSelection() method. I believe it does what you want.
EDIT: If you want to clear the selection:
JTable table = ...;
table.getSelectionModel().clearSelection();
if someone else have similar problem with ADF and JTable here is solution. I achieve that by overriding first() on the VO impl. my problem can be solved.
That comes in handy in many situations:
no selection after refresh (just return null from first())
reselect a particular row after refresh (before refresh, store a row key, after refresh in first() if stored key is found, navigate to that row and return that from first())
find next matching row for user to work on after refresh of a worklist
avoid costly detail executions in a VL situation
I have a jTable with columns 'Job_no' and 'Status'with values such as:
Job_no Status
1 Active
2 Pending
3 Pending
I would like it so that if a user clicks on a Status say in this case the first 'Pending'(where Job_no = 2) an inputDialog pops up allowing the user to change the status of the cell clicked-how can I do this? Bear in mind you will also have to retrieve the Job_no(that corresponds to that status) somehow, and that, though I'm OK with JOptionPane's, I'm new to JTables. I'm using JDBC(mySQL) and have a table 'Jobs' which amongst other things, has column Job_no and status.
Thanks for your help.
You don't do that by using a mouse listener and a popup, you just make the cells editable, and perhaps set a custom TableCellEditor. Take a look at the Java Tutorial for more details.
1) add a MouseListener to the JTable
2) Read the JTable API for the methods that will convert a mouse point to a row/column
3) Now that you know the row/column you can use the getValueAt(...) method to query the data in the Job_no column
4) Then you can change the status of the selected cell using the setValueAt(...) method.
So you break the problem down one step at a time.
The desired behavior is akin to the mirrored text editing field provided in Excel when a given cell is selected, allowing more space to view the contents of the cell. I have a JTable with 5 columns and n rows. Column 2 holds expressions that can be arbitrarily long, thus I'd like to provide a separate JTextField to work with for editing the contents of the expression cell per row. The other fields are directly editable in the table. When the user clicks on a field in column 2, however, I want to send them to the text field. Any contents preexisting in the cell should be appear in the text field and additional edits in the text field should be mirrored in the table cell. Likewise, if someone double-clicks on the cell and edits it directly, I want those changes reflected in the text field. Thus, the user can choose to edit in either space and both are updated. Ideally, they are updated per keystroke, but update upon hitting return is acceptable.
So, far I've got the JTable, TableModel, TableModelListener, JTextField, ListSelectionListener, and AbstractAction, working together to provide most of the functionality described above. I'm missing the reflection of direct table cell edits to the text field and per-keystoke updates.
Are their ideas on how best to construct this behavior?
Well, if you want to get data from the table to the cell then you add the code to your TableModel's setValueAt() function, which should run when the user changes the content in an editable cell. I don't think that will update per-keystroke though.
If you want to move data from the textbox to the table cell use code like this
myJTextField.getDocument().addDocumentListener(new MyDocumentListener());
Where MyDocumentListener is an implementation of the javax.swing.event.DocumentListener interface
That will get you per-keystroke updates from the box to the table. But for the other way around it's a bit trickier.
There are two ways you might be able to go about doing it
1) Add a key listener to the table, and when the user starts typing check to see what table element is active, and intercept keystrokes as they type. That's kind of messy, though.
2) Another option might be to try to grab or replace the component that the table is using to actually let the user make the changes. I think that JTable actually allows you to change the editor component if you dig around.
I was looking for an answer for a previous question and had an ingenious idea to overcome a limit on JTable. I need the editor to be different on a row by row basis, whereas JTable can only handle a single editor for each column.
So my idea is to use a MouseListener to check the row and column on the JTable and set new editor each time.
But, calling setCellEditor() a second time do not have any effect. The editor remains to be the first one that was set. So how can I make "setCellEditor" work a second time for the same column?
Here's the code in MouseListener.
public void mouseClicked(MouseEvent e) {
int cols = resultTable.columnAtPoint(new Point(e.getX(), e.getY()));
int rows = resultTable.rowAtPoint(new Point(e.getX(), e.getY()));
StorageObject item = (StorageObject) resultTable.getModel().getValueAt(rows, cols);
TableColumn col = resultTable.getColumnModel().getColumn(cols);
col.setCellEditor(new MyComboBoxEditor(item.list));
}
I'm not sure why your code isn't working (it's been a while since I've done Swing), but why don't you just override
public TableCellEditor getCellEditor(int row, int column)
On your JTable? Maintain a map of the combo boxes you want to use for each row and in your overriden method return the correct one.
My theory is that when all the mouse listeners registered to the Table/TableCell are invoked, the ones installed to the API classes by default will be invoked first, before your mouse listener. This means the event causing the editor to be fetched will occur before you set it to a different one. Kind of like a race condition, only it's actually defined somewhere in the API source code... That's my naive theory and I can already see some holes in it, so on to my solution:
Override JTable.getCellEditor(int row, int col). This allows you to return whatever editor you want for any cell.