I would like to highlight specific rows in a JTable whenever the contents of the a cell match with an input from the user. The following code is what I have that works thus far:
JTable table = new JTable(model) {
public Component prepareRenderer(
TableCellRenderer renderer, int row,
int column) {
Component c = super.prepareRenderer(renderer,
row, column);
if (!isRowSelected(row) ) {
c.setBackground((hashMapcontainer
.containsKey(row)) ? Color.GREEN
: getBackground());
}
return c;
}
@Override
public boolean isCellEditable(int row, int column) {
return false;
}
};
Notes: hashMapcontainer
is a hashmap
that is globally scoped within the source file.
Now this works to some extent however, I am adding this JTable
to a JTabbedPane
that is within a JFrame
. JTables are dynamically created throughout the runtime of the program. However, the prepareRenderer
method causes all the specific cells in all the created JTables to be highlighted.
How can I keep cells in all the JTables to keep their own specific highlighted cells rather than having all the JTables with the same exact highlighted cells in each?
Thanks in advance!
The renderers are "rubber stamps". That basically means that they carry there previous settings over to the next cell.
What you need to do is provide a "default" behavior
While I personally think that
prepareRenderer
in this case is probably a fair solution, you really should explore the possibly of providing a base line renderer. This is a lot of work to get right but has the advantage of been portable (if you change table implementations) as well as allowing other people the chance to define the highlight rules of a given cell, which you've basically just gone and overridden, IMHO.I'd also suggest taking a look at JXTable as it has in built highlighting
Generally, overriding methods on the basic Swing classes is a bad idea. The recommended approach is to create a
Jcomponent
that implementsTableCellRenderer
and apply it to the table withsetDefaultRenderer()
. Note that by default JTable supplies 3 of these for Object, Number, and Boolean types. Typically, a renderer looks something like this:This gives you a reusable component, rather than needing to extend JTable every place you create it. As for the same cells selecting in all tables, that is due to
isRowSelected
andhashMapContainer
accessing global state instead of per-instance state. AllJComponent
s havegetClientProperty
andputClientProperty
. These allow you to attach your own state object to aJTable
. Then yourisRowSelected
becomesisRowSelected(table, row)
, which simply calls:Like wise the
hashMapContainer
can also be retrieved from the table:Update:
This is pretty much the same for a dynamically generated table. Table creation will look something like this:
It's worth noting that as long as the renderer carries no state there is no need to create an instance per table. I'll usually create one and use it for all my tables.
Here's an update to the renderer above that does not use global state, rather looks to the table for properties: