I have a custom JTable (15 rows by 20 cols) that was created to work for all JComponents. I'm currently using it for a mixture of JComboBoxes, JTextFields, and JButtons. Oh, and I'm using Java5 (a requirement).
I have two questions:
1) The first regards the TableCellRenderer class, and its single method:
public Component getTableCellRendererComponent(final JTable table,
final Object value,
final boolean isSelected,
final boolean hasFocus,
final int row,
final int column) {...}
All it does is cast the Object value argument to a JComponent, and potentially change the background color. No big deal. The question I have is why is this method is called sooooo often. When selecting a single cell, it is called 23 times. When Alt-Tabbing between two UNRELATED applications (I use Win7), this method is called over 200 times (and only for JButtons and JTextFields)!
Is this in any way necessary, and if not, how can I put a stop to unnecessary rendering calls?
2) The second question regards the JTable itself. When I'm editing a cell (cursor in a JTextField and blinking) and I click on another cell, that cell is only selected. If I then click on another cell, however, I start editing that cell. All I can think is that from the initial editing component, I'm selecting the JTable, and then selecting the component within. Is there any way to change this? Either going one way (always selects the jtable on first click) or the other (always enters cell on first click). I would prefer the first option, if possible.
Thansk to anyone who can grant some insight/help!
1) Why are you storing Components in the TableModel? That is not efficient. You should be storing data in the TableModel. JTable was designed to render data using a single component. The default renderer is generally a JLabel. Then when you edit a cell a different component is used.
When you click on a cell you may need to re-render the previous row (to remove the row selection) and then render the current row with the selection. So the renderer is called for each visible cell that is affected. Tabbing to the application probably causes all the visible cells to be re-rendererd.
2) Hard to answer since this is not the default behavour. You must also be using custom editors and I don't know what your custom code looks like. The default editor has a setClickCountToStart() method which defaults to 2. Maybe you set this to 1.
Change your solution to use data (not Components) in the TableModel and post your SSCCE if you have further questions.
Related
I need to customise the selection behaviour of the cells inside a JTable descendant. I have a custom cell editor using a JTextField descendant as the editorComponent; there's a focus listener registered on it which manages the desired selection behaviour.
I need different behaviour when tabbing around the table than when another window or application comes to the front and then goes away again.
This is currently not possible, because the cell editor's editorComponent seems to have no off-the-shelf way of knowing (or telling it) that it's the editor for a table cell, so it doesn't know that it's "inside" the table, so my focusGained() and focusLost() think focus is moving between different windows even if I'm just tabbing around in the table.
SwingUtilities.windowForComponent() returns null for the editorComponent.
Before I roll my own solution, is there an accepted way of dealing with this issue? I can't be the first person to need to do this...
I'm writing an application that has a JTable, and an edit button that sets the current selected row to be editable. Then once the user is done altering the data, they can click the edit button again (with text that now says "Save") to save the data.
The problem is though, when I set a row to be editable, there isn't a visible difference. I could add some code to the renderer to draw the editable cells a little differently, but I don't know what the proper way to make a cell look editable is. Change the color? Make it look like a JTextField? What's the standard method?
Thanks!
Really this is a user interface design question, not a programming one.
To do what you want you need to supply an appropriate cell renderer with the changes you desire but you will need to decide on your own settings. One option might just be to look at the difference between an editable and non-editable text area and apply those to all the cells on the table. This may be as simple as setting the renderers to disabled for any read-only rows.
I am using a custom cell renderer that implements TableCellRenderer and displays JTextArea (instead of JLabel) for each row. I am basically overriding getTableCellRendererComponent(...) method with mine which does some additional calculations per row. These calculations have to be done just once per table update. Since getTableCellRendererComponent method is being called with every mouse move, lag occurs. So I thought I should prevent getTableCellRendererComponent from being called to avoid lag.
Considerations:
1) My table has only 1 column and has no header.
2) My data is static and is read from an ArrayList by getValueAt(int row, int column) method in a custom tablemodel class implementing AbstractTableModel.
3) I don't need to watch over mouse motion events.
4) I don't expect much data, so I might want to display whole table at once or cache it completely.
5) Most lag is caused by setting text each time when returning from getTableCellRendererComponent, because some rows are using Right-to-Left chars and RTL text requires extra time to render.
Do not try to limit the number of getTableCellRendererComponent calls. Instead, make your implementation of the renderer better by caching the results of the calculation.
You can easily add a listener to the tablemodel so that your renderer knows when the model is updated. Only then it should mark that the stored calculation results are invalid, and recalculate them on the next getTableCellRendererComponent call.
I have an editable JTable. If a user is editing a cell when the underlying row model is updated the cell editor loses focus.
What's the simplest solution to this?
The simplest solution to this, as #mKorbel noticed, very theoretical question :) is to:
Always remember which cell has the focus.
Listen to row changes.
When the underlying row is changed at the end of the method, called after the change is done, give back the focus to the right cell, e.g. using requestFocus(), example available here.
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.