• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other Pie Elite all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Jeanne Boyarsky
  • Ron McLeod
  • Paul Clapham
  • Liutauras Vilda
Sheriffs:
  • paul wheaton
  • Rob Spoor
  • Devaka Cooray
Saloon Keepers:
  • Stephan van Hulst
  • Tim Holloway
  • Carey Brown
  • Frits Walraven
  • Tim Moores
Bartenders:
  • Mikalai Zaikin

ideas wanted on making this custom JTable cell renderer more efficient

 
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator
I want to fill the column value in a given row with rectangular blocks that represent a percentage of data from the row. I would like this column to be the last in the display, and to change size when the window changes size. I want to be able to set a color and a label on each rectangular block

I have the following code working:

If you stretch the window, the blocks within rows in the second column change width to maintain the percentage they represent.

Currently I do this by creating a JPanel with a line_axis boxlayout, and putting JLabel components into it that each have the correct width.
I know a renderer is not really supposed to create the component, but rather a "template" for a component. I struggle a bit with that conceptually; I sort of know what they mean, but implementing it that way in this instance escapes me. Perhaps it does not apply here.

As you can see, the renderer creates a lot of components, and it does this multiple times during a resize. I would like ideas on how to make this more efficient in terms of object creation.

I am not wedded to this style of custom renderer, it is just where I thought the solution would lie. If someone has a completely different idea on how to approach the overall problem, I'd be happy to listen to that, too.

Something that just occurred to me was to create these objects one time and then stick them back into the data model, where I could retrieve them and adjust their sizes instead of creating new ones. But putting my UI components into the data model seems real ugly, and I am still hoping someone will suggest a better approach.

rc
 
Rancher
Posts: 3324
32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

I would like ideas on how to make this more efficient in terms of object creation.



A renderer is designed to be reused. Based on your example you have a fixed number of values for each row in the second columns. Therefore you can create a panel with a fixed number of components and just reset the text for each component. Something like:



Note, you really don't have a proble TableModel for this. You really should be storing a custom object in the model to represent the data for the second column. This object would contain the text as well as the array of percentages. It could also contain an array of colors for each of the percentages.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Rob Camick wrote:

I would like ideas on how to make this more efficient in terms of object creation.



A renderer is designed to be reused. Based on your example you have a fixed number of values for each row in the second columns.

-> this shows the limitations of examples. No, my data is not set up so that there are always the same number of percentages for each row, there might be 1, or 4, or 20. The info you've given me is valuable nonetheless, it was not clear to me to declare instance vars in the renderer class and reset their values each time getCellRendererComponent is called.

However, this won't quite cover my case. I don't even have a fixed number of percentages in the display after the table is rendered! If the user widens the window enough, he can see percentages that were too small to display when the window was narrower.

So, do you (or does anyone) have ideas about how to handle this when there are different number of percentages per row, and in fact potentially a different number when the display opens.

[And I know about using data models, etc.; I thought this was a simpler example to illustrate what I wanted to do.]

 
Rob Camick
Rancher
Posts: 3324
32
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

No, my data is not set up so that there are always the same number of percentages for each row, there might be 1, or 4, or 20



Maybe you determine what the maximum will be and define that number of labels to add to the panel. Then as you process each cell you set the size for each percentage. For the remaining labels you can set them invisible so they aren't painted, or you can set the size to 0 so it isn't painted.

Or maybe you keep a map of panels with a different number of visible labels. Then you retrieve the appropriate panel from the map for each cell. If the map doesn't contain a panel with the required number of labels you create one. That way you don't have to set an artificial limit. or worry about hiding components.

If the user widens the window enough, he can see percentages that were too small to display when the window was narrower.



Not sure I understand this. I would guess you still have the same number of labels added to the panel. Its jus that the size changes as the window widens so more labels will be readable.
 
Ralph Cook
Ranch Hand
Posts: 479
  • Mark post as helpful
  • send pies
    Number of slices to send:
    Optional 'thank-you' note:
  • Quote
  • Report post to moderator

Not sure I understand this. I would guess you still have the same number of labels added to the panel. Its jus that the size changes as the window widens so more labels will be readable.



Well, no, I really meant that, if the block is going to be too small to display its label reasonably, then I don't display it at all. So the number of labels in the panel in that cell in that column can change when the user narrows or widens the screen.

I finally got this working based on your suggestion, and appreciate your help. The Dimension instance that I had to create each time bugged me, so I tried making that an instance variable as well. But that makes all those panels the same size!

I think what happens is this -- this "template" that is being created for the display component in this routine has to be completely ready to display the entire component at the end of the routine. I suspect they do something like have it do its normal paint routine, but on top of the table rather than on the components within the routine. This would explain the Dimension-related behavior -- at the end of the routine there is only one dimension, so all the labels would be the same size.

So I made an array of dimensions just like I have of labels, and refer to them in the same loop. That works. I am posting the resulting code below for your edification and enjoyment.

I have a better understanding of renderers now, and have my own offering for the explanation of what is meant by the renderer being a "template" for the component displayed:

"A Cell Renderer returns a component, but the component returned is not actually put onto the cell; the runtime uses the component to decide how to draw that cell, and then the component is free to be used again (such as for the next cell). Therefore, when the GetTableCellRendererComponent() method is complete, the component that it returns must have been arranged to look like the cell to be drawn."

A thing to keep in mind about custom renderers, then, is that you do not have the luxury of creating an object, using it to affect a sub-component in your renderer, and then re-using the object. At the end of the routine, all sub-objects must have their own characteristics and relationships extant, because those sub-components are not actually going to be put on the table.

>
reply
    Bookmark Topic Watch Topic
  • New Topic