aspose file tools*
The moose likes Swing / AWT / SWT and the fly likes How to color JTable cell without a renderer? Big Moose Saloon
  Search | Java FAQ | Recent Topics | Flagged Topics | Hot Topics | Zero Replies
Register / Login
JavaRanch » Java Forums » Java » Swing / AWT / SWT
Bookmark "How to color JTable cell without a renderer? " Watch "How to color JTable cell without a renderer? " New topic
Author

How to color JTable cell without a renderer?

Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45

you've added another field for the value, but forgot to add another field for color. So you need to modify MyColorRow and MyColorModel to support different colors of different columns in a row.

Martin,
now i got really confused.Why i need two colors if i only paint one cell each time?The model only notifies the chenge with setColor, how i change the model?With a color array???

Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Have a look at the renderer code. It calls model.getColorAt(row, column) to obtain the color of a cell. But the model's getColorAt() method doesn't use the column index at all -- it returns the same color to all cells in the row.

To correct this situation, you need to decide whether you want to colorize only the first column, or both.

1) Colorize both columns: the table row can currently keep only one color. It has the value, value2 (added by you) and color fields. You'd need to add a field to keep additional color information and modify the getColorAt() and setColorAt() methods to take column indexes into account. You've already made similar change when you've added the second column (and the value2 field).

Of course, you need the logic to set colors of the cells in the second column, perhaps as part of the AnalyzeButton logic.


2) Colorize only the first column: several options are possible, but the easiest one would be not to set the MyColorRenderer to columns you don't want to colorize. That is, remove the following line from the code:
(There are other possibilities, such as modifying the model's getColorAt() method to return null for the second column.)
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
i think i get it now...but:
How can i make my code more friendly to use?I have 5 other classes who need the same: Evaluate two columns of JTable and color.The only difference is the cell position(some are 0 and 1, others 8 and 9...).I will have to create 6 models,6 different colorows....more 6 different AnalyzeButtons...wow!
Another thing:What s the problem with MyColorRenderer other user has talked about it?


Best Wishes and thanks for your useful help,

Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
i changed my code to accept two Colors, but i still get all colums BLUE even if i do that in Analyze Button:

My setColorAt is now:


BestWishes,

Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
i saw my mistake:Its my getColorAt!How i should modify that(i can t return two colors...)?One Color array?

Best Wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

The setColorAt/GetColorAt methods handle one cell at coordinates given by the row and column index. You don't want to associate two colors with one cell.

Have a look at the setValueAt method:You've handled this one correctly. The setColorAt method would be analogous - don't add the fourth parameter (color2), but use the columnIndex parameter to store the color in the proper field of the MyColorRow instance instead.

Similarly, the getColorAt will be analogous to the getValueAt method. That is, it will return one color of the cell at given (rowIndex, columnIndex) coordinates.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul Hayabusa wrote:How can i make my code more friendly to use?I have 5 other classes who need the same: Evaluate two columns of JTable and color.The only difference is the cell position(some are 0 and 1, others 8 and 9...).I will have to create 6 models,6 different colorows....more 6 different AnalyzeButtons...wow!

You should avoid code repetition, of course. You need to find out what all these components (models, renderers, buttons and so on) have in common. In this case, if the only difference is the position of the columns, then you very probably could modify all these components to keep the column positions as parameters given to them in constructor (or setter methods, but in constructors it probably could be easier). Then you'd have a common code for all.

This is actually a design question. Doing the design right is not easy, it requires a lot of though and at least some experience. But no one can learn it unless he tries, so do try . It is not uncommon to choose a design, code it and then discover that another way might perhaps be even better. That's a good sign, actually, it means that you're learning.

Another thing:What s the problem with MyColorRenderer other user has talked about it?

The problem basically is that JTable supports column and row reordering. Columns can be reordered by user dragging them (by their header) into a new position, and rows can be reordered by setting a RowSorter on the table. JTable makes this possible by maintaining a mapping of the model's coordinates into the view's coordinates (and vice versa).

The renderer's getTableCellRendererComponent method is called with view coordinates. (Note: I don't know why, as it doesn't know the exact position of the cell being drawn anyway. Passing in model coordinates would be more useful in my opinion.) You normally don't need to translate the coordinates, since the value of the cell being drawn is passed as a parameter to that method too, and JTable makes sure to pass in the correct value. But if you want to access other properties of the model, you need to convert the view coordinates to model coordinates. JTable has these functions to do the conversion: convertColumnIndexToModel, convertColumnIndexToView, convertRowIndexToView and convertRowIndexToModel. The ToModel / ToView suffixes indicate the target coordinate system, obviously.

There is another option that I'll mention only briefly: you could create a class to pass all the formation the renderer needs as a single object, and the model's getValueAt method could provide this object. In our case, the object would contain the value and color fields. Then you wouldn't need to look up the color in the model separately, and therefore wouldn't need to mess up with the view/model coordinate translation.
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45

Martin,
i changed my model:


My AnalyzeButton:

But i am having the same bizarre behavior:
Color(with BLUE) the cells with value different than 40.
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul, have a look at your code and try to find out where does the color used by the renderer come from. Say that the renderer paints cell at (0,0). It asks the model to provide the color for (0,0). What does the model do? Where does it look? Then do the same for cell at (0,1) - row "zero", column "one". Where does this color come from? Is it ever possible that these two cells will be painted in different color?
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
doing some tests i put a RED value to be evaluated too...and dang!Sometimes colors RED(all cells in that row), other BLUE, never one BLUE and other RED(even if i put 40 and 50 in each cell in the same ROW).
there is something wrong with my logic:


Best Wishes,

Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul, there is a little bug in your code. It can be found in the last version of the MyColorModel class you posted on Wednesday. Doing more tests by adding further modifications to the code won't help until you remove that bug.

I believe you'll learn a lot if you try to find this bug yourself. It is possible to spot it just by looking at the code. We (the developers) are sometimes tempted to run the debugger or tweak the code here and there in a hope - usually false - that the bug will just out of the code right into our eyes. Much more productive way to go about this is to just sit down and think - why does the code behave the way I'm seeing?

Try to answer the questions I've posted in my last post, just by looking at the code. You don't need to run it, test it or debug it, but you do need to understand what the code is doing. So, again: where does the color for left column come from? Where does the color for the right column come from? After you figure this you, you'll immediately see where the problem is.
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin, i found the bug!It was:


After changing that, i am getting the error after i press my JButton:

Always when i edit a cell!And the coloring only in one color per row continues!

Best Wishes,

Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul Hayabusa wrote:Martin, i found the bug!It was:

Yes, that was indeed a bug. But I missed that one.

And the coloring only in one color per row continues!

This is the bug I was talking about. The questions I've asked you should lead you to the source of this bug.

If you experience other problems, you'll have to post the code - and describe the problems - once again. But I'd prefer that you solve the coloring bug first.
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
yeah, i saw a part of my mistake when you told me to search the cell postition!Thanks!About the model:I was working with only two columns when there is three...
I changed my model:

And my JButton was onle getting the first column, i fiexed that with a for for columns:


But i am still getting the same behavior(it colors ALL rows).Where i am wrong?


Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul Hayabusa wrote:yeah, i saw a part of my mistake when you told me to search the cell postition!

So you did find the coloring bug?
But i am still getting the same behavior(it colors ALL rows).Where i am wrong?

Or not?

If you really traced the origins of the color used in the renderer, you'd probably see the bug for yourself. I'll ask you an additional question: how many different colors can the MyColorRow class store? And, given that one row is represented by exactly one instance of this class, can one row ever be rendered in more than one color?
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
I'll ask you an additional question: how many different colors can the MyColorRow class store? And, given that one row is represented by exactly one instance of this
class, can one row ever be rendered in more than one color?


Martin,
i must be blind or something like that, i can not see your point on the model.MyColorRow can store only ONE color per instance.But how can i change that,
if the model is not CELL oriented?How can i tie that to have two idependent cell color working?I talked with you earlier about one Color array(or two colors per row), but it wasn t the step needed.
I am confused all over again...


Best wishes,
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
If you really traced the origins of the color used in the renderer, you'd probably see the bug for yourself.

Oh, i forgot to tell:after i changed my model, it colors only one ROW and that ROW with just one color(Blue or Red).I need to color all rows but each cell with their respective colors(and value to be analyzed) . You told i have something to REMOVE from my table model, but i cant see what.

best wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul Hayabusa wrote:MyColorRow can store only ONE color per instance.But how can i change that, if the model is not CELL oriented?How can i tie that to have two idependent cell color working?

The original code I've provided supported only one value and color per row. You have expanded it to support two values per row - by adding the value2 field to it. Supporting two colors per row can be done very similarly - by adding another Color field, it this case very probably named color2. I had thought this will be easy, since you've added another column and a field for its value, including modifications to the model, without any apparent problems.

Of course, my code was just an example. In the real world, I'd expect you to use better names for the fields, for example minValue, maxValue, minColor, maxColor.

It would be possible to create a cell-oriented model. You could have a two-dimensional array of cells, and each cell could keep the value, color and perhaps other formatting attributes. However, from your original description, I don't think cell oriented model is a good fit. The columns in your model have a well defined and fixed meaning, in my opinion a class representing an entire row with properly named fields is much better in this case.

Paul Hayabusa wrote:You told i have something to REMOVE from my table model, but i cant see what.

Are you sure? I'm not aware of this advice, and can't find that in any of my posts in this thread. In any case, I'm sorry if my instructions have seemed somewhat cryptic to you, but I was trying to let you spot the problem and the solution for it. But I'm really not a good teacher.

I'd like to reiterate my original goal at this point: the code I provided was meant to illustrate how it is possible to contain all information (value, color etc.) needed to display in the table in the model. This simplifies the usage of JTable a lot. Do you now understand what I mean?
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
in friday you told me:
It can be found in the last version of the MyColorModel class you posted on Wednesday. Doing more tests by adding further modifications to the code won't help until you remove that bug.

Thats what i understood of something to remove in my MyColorModel class.

I had thought this will be easy, since you've added another column and a field for its value, including modifications to the model, without any apparent problems.

I believe i misunderstood what you wrote when you told me to change setColorAt/getColorAt.when you told me:
You don't want to associate two colors with one cell.

I killed my way using two colors in MyColorRow.You are meaning ONLY the methods in MyTableModel.

I think now i am almost there:
MyJButton:

My Model:

MyColorRow:

and i create the same way as before, but just with one more field:


I dont have anymore the problem of color ALL rows.It is working near what i need, but i have still a problem:
Color just ONE cell per row(no matter if is in the first column or second) at a time.Should evaluate all cells in column 0 and 1 and color(if it matches the criteria in JButton).
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
I dont have anymore the problem of color ALL rows.

Just explaining a little better myself:
What i mean is not coloring all cells even if i dont modify nothing.But i expect to color both cells in the same color, if they are 40,40 or 50,50 of course.

But I'm really not a good teacher.

Martin,
you are a great one.I am a bit slow in the uptake(i am a survivor of a car crash very young where i lost a bit of brain mass).Is not your fault.Sometimes, i have to read two,three times to understand well what is being told.

best wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul, I'll be quite busy in the rest of this week. If you want, please post your current full code, so that I know we're both looking at the same version. I can't promise I'll get to it in the next few days, though.
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin, all code below:

Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Just a minor correction in code above, the correct AnalyzeButton is that:

Its working way better than before, but i still get some erros like:
-Colors when i change a value(if i am changing a colored value of 40 and put 400, that value remain blue after i press my JButton)
-The last row dont always update
-I am sill receiving(from time to time) a
in the lines i have called setColorAt.

Best Wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Hi Paul,

I've been able to identify these issues:

In the AnalyzeButton.actionPerformed there is this code:
1) When the value is 40 or 50, the other ifs don't evaluate. So if the first cell is colorized, the other one won't be.

2) If the cell changes its value from 40 or 50 to something else, it is not "decolorized". You should probably place a final else there that would set the color to null.

3) In the same method, there is a for-loop over all columns in the model. You can just remove this loop - you're accessing the columns directly, not in a loop.



4) In the MyColorModel.setColorAt() there is this line of code:Have a closer look at the method which is called here (eg. read its Javadoc and inspect its parameters carefully). Hint: have a look at the setValueAt method, it contains a similar line which is correct. This is the reason why some exceptions are popping here and there in your code.


[Note: I assume this is your hobby project. Even in this case, I'd suggest you to use a version control software. Firstly, you'll learn how to use it - and it is immensely useful -, and secondly you'll have the history of your project at your disposal, which helps to identify errors (you can compare the last working version with a current one when you introduce a bug, which makes it far easier to see which change broke the program). I'd suggest to use git or Mercurial (Mercurial might be easier to use if you have previous experience with CVS or SVN), but there might be other options out there.]
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
about 4) Many thanks!!!I will be an old man and never be able to find out that mistake!Incredible!

About 1,2,3:
I corrected the for, and made some changes:

But dont workswell... there is some way more elegant to test two colums at same time without tie my code with a bunch of if´s or i will have to do always something like that:

Best Wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Paul Hayabusa wrote:But dont workswell... there is some way more elegant to test two colums at same time without tie my code with a bunch of if´s or i will have to do always something like that:


Well, I thought you didn't want to test two columns at the same time, but the opposite: that the value of first column doesn't affect the color of the second column and vice versa (the value of second column doesn't affect the color of the first column). If this is true, you could write a separate method for coloring the first column and the second column, or - perhaps even better - a method that would take an int value of the cell and returned the color (or null if there should be no explicit coloring). You'll don't need to evaluate the value and value2 in the same if condition.
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45

If this is true, you could write a separate method for coloring the first column and the second column, or - perhaps even better - a method that would take an int value of the cell and returned the color (or null if there should be no explicit coloring). You'll don't need to evaluate the value and value2 in the same if condition
.
Martin,
to be truthful, when an user press Analyze button, it will be expected the two(in the rows presented) to be analyzed.I like that approach:
How i can make a generic coloring method?(Remember: i have six classes doing the same the only difference is the cell position).


About my project: Its READY(Reports with Jasper,Graphics with JFreechart), except the colorization.Its about sports statistics(Athletics,Swimming...)


BestWishes,

Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
once more, i think i didn t express myself correctly when i told i want the whole row analyzed.Sorry.
What i mean it, i wanna the value of the two significative cells analyzed in the rows each time the user press button. If a user entered 40 and 50, i expect the color be BLUE and RED.Thats the why i was using the for column(unnecessary).

a method that would take an int value of the cell and returned the color (or null if there should be no explicit coloring). You'll don't need to evaluate the value and value2 in the same if condition.

It should avoid a lot of pain...how i can do that?I get the Model(i mean My Table Model) in that method?

Best Wishes,
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45
Martin,
when you mean a method to take the int value of the cell, you mean something like that:

and calling:

That is it?And how can i make the method to evaluate correctly two cells per interaction?Only by IFs?Or a for for the column?

Best Wishes,
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Is the coloring logic identical for each of the two columns to be colored? If it is, I'd suggest to create one method which would take the value of the column as a parameter and returned the desired color. The code for coloring one row could then look like:The indexes of the columns to be colored are hard-coded in this example, but you could easily store them in a member variable instead; that might help you using the same code for all of your six different table models (in which the position of the columns to be colored may differ).

This is what I had on my mind. If the coloring logic of the first and second column are different, I'd still create a separate method for each of these logic and just called the right method with the appropriate column index.

(There is again a coordinate system bug in the actionPerformed method in the AnalyzeButton constructor. You're obtaining a value using table.getValueAt() and using this value to set the color using tableModel.setColorAt(). You'd have to either translate the coordinates using methods I've mentioned before, but much easier would be to obtain the values by calling the model's method, not table's method. I wasn't paying enough attention the last time and missed the bug.)
Paul Hayabusa
Ranch Hand

Joined: Jan 17, 2013
Posts: 45

Martin,
yes...the two columns have the same behaviour!

I tried that:

And in JButton:


Of course, because of the read of all columns, i got a ClassCastException error and dont works fine.

About your method: Superb!Almost flawless!The only problem is when i edit, they remain the prior color till i have pressed jbutton.
I will change that controlling cell Focus.

For everyone in trouble, the final code(Thanks Martin) is:

and Analyze JButton:

It works no matter how many cells you have!

Many thanks for you help...incredible how ridiculous(and simple) your method works!
Best Wishes!!!
Martin Vajsar
Sheriff

Joined: Aug 22, 2010
Posts: 3610
    
  60

Glad you got it working, Paul!

Paul Hayabusa wrote:
The only problem is when i edit, they remain the prior color till i have pressed jbutton.
I will change that controlling cell Focus.

Uh-oh. This behavior was explicitly requested in the initial specification. If the coloring should always reflect the actual value, probably the right thing to do would be to implement the logic in the renderer, but it can be done by small changes in the current code. Instead of handling cell focus, however, I'd suggest to recalculate the color in the model's setValueAt() method.

Please also note that the switch statement only works with constants. If the "40" and "50" are replaced by variables, you'll still have to use a bunch of if statements instead of switch.
 
It is sorta covered in the JavaRanch Style Guide.
 
subject: How to color JTable cell without a renderer?