Skip to main content

JXLabel::setBackground issue

6 replies [Last post]
swebb99
Offline
Joined: 2007-06-26
Points: 0

As of release 1.6.2 setBackground in JXLabel is this

@Override
public void setBackground(Color bg) {
super.setBackground(bg);

SwingXUtilities.installBackground(this, bg);
}
Now this caused a bug in my software release. I was creating a JXLabel as part of a renderer for a combo popup. The label used a painter (used as a background painter) to highlight certain text in the label. I used to set the background painter on the label and then set the background of the label. However now that the change above was made in 1.6.2 this highlighting of the text stopped working. The reason? Well installBackground overwrites my painter with BackgroundPainter!!!!
This strikes me a dubious behaviour as now the ordering of setting background color and background painters matters !!!

My 2p

Steve

Reply viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.
kschaefe
Offline
Joined: 2006-06-08
Points: 0

This is the result of Issue 964 where UI delegate installed painters can hide the user set background. As part of the update the package documentation was updated to explain the current behavior for components that have background painters. Here's the philosophy: if you're using background painters, then you should use them. If you're not then, you can continue to set background colors and have those take effect as you expect. This means that colors should be set before painters. An overview of the logic is as follows, when setting a color:
1. If color is ui resource and painter is uiresource install color as the painter ui resource
2. If color is ui resource, but painter is not do nothing
3. If color is not a ui resource install is as a painter
I think 1 and 2 are clearly correct, but I can be persuaded to change the behavior of 3. This means that the last one in usually wins. This attempts to strike a balance between old habits and new methods.
My gut feeling is, if you're already supplying a background painter, why not go all the way and have it paint the color you are supplying as well?
Karl

swebb99
Offline
Joined: 2007-06-26
Points: 0

Ok thanks for the reply Karl, I should obviously pay more attention to the JavaDoc!
In my case I have a white background on a label used in the comboxbox drop down cell renderer and I highlight and matching text using a coloured rectangle under the text. So basically I should probably be using the painter to paint the entire background white and then the rectangle(s) in the appropriate colour. Sound reasonable, I should tweak the painter and remove the setBackground :)
Thanks

Steve

kschaefe
Offline
Joined: 2006-06-08
Points: 0

Steve,
Not a problem. I always appreciate your feedback. I think clearly, we should add some extra documentation on the background-painter enabled components, particulary the overridden setBackground methods. Package documentation is good, but on method would be better.
Karl

swebb99
Offline
Joined: 2007-06-26
Points: 0

One other thing Karl. I also have a highlighter on the rows in a table and some of the table cells use a background painter to highlight specific text in the cell. Now if the highlighter is triggered is overrides the background by default on the renderer which obviously dumps over the background painter. What I will need to do is test if a background painter is being used and then updates it background colour and not the renderer.
It maybe worth considering testing for installed background painters in the swingx code within the supplied highlighter classes. Maybe create a background painter interface (with setBackground() method) which indicates that any painter implementing this interface can deal with coloring of the background and hence the setBackground method should be called on the painter rather than the component!
One other point. I would like in my code to test if a component/renderer is backgroundpaintable so I can then know I can make the getBackgroundPainter method on it. However for some reason this interface is not public!.This seems a little odd!

Just a thought.

Steve

kschaefe
Offline
Joined: 2006-06-08
Points: 0

Steve,
The default renderers that SwingX provides do not come with any painters installed and do not use this painting logic. There's one hole that I need to fix. But how? Perhaps the right thing to do is check whether the component's parent is a CellRendererPane (making the class a renderer) and use pre-bug-fix logic? Need to think about that.
As for BackgroundPaintable, I introduced that interface so I could create utility painting code that did not require casting. The type constraint for the code is <C extends JComponent & BackgroundPaintable>, which allows me to work with the background painter as a trait or aspect attached to a JComponent. I didn't expect that people would want to have BackgroundPaintable be part of the public type hierarchy. We can always add the public modifier to it, but why do you need to access the painter? Can you give me a little more on this use case?
Karl

swebb99
Offline
Joined: 2007-06-26
Points: 0

Hi Karl,
In my case I have created a RegexTextHighlightPainter class. This class is passed a Pattern, and background and highlight colors in the constructor. Because of the initial issue I raised the painter now fills in the entire backgound with the background color specified (so setBackground should not be called on the component) and it then paints rectangles under any text in the component that matches with the pattern. In short it highlights text matches.
The painter at the moment is only used on JXLabels and I also started using it to paint the background of cells in a JXTable. Basically I have a cellrenderer which instead of passing a JLabel back it passes a JXLabel, my Regex painter is used to highlight any matching text in the cell that a user enters in a search field elsewhere on a form. However the table also makes use of a extended ColorHighlighter to highlight specific rows in the table based on a predicate. On any un-highlighted rows my Regex painter shows the matches in a cell highlighted, however if a row is highlighed this sets the background on the renderer on every cell in that row, basically the setBackground removes the painter so the JXLabel no longer has the Regex painter on it so the search highlights are lost on those cells.
I was thinking that if the highlighter could test that if the renderer implemented the BackgroundPaintable interface then they could then test if a background painter was installed, this would indicate to possibly not call setBackground on the renderer. If a new interface was written (PainterPaintsBackground - defining a setBackground method) that could be implemented by any Painter that looked ofter painting a components background. Any highlighter could then test if the background painter on a renderer implemented PainterPaintsBackground and if so call setBackground on the painter rather than the renderer. In this way background highlighters and painters could potentially coexist.
I guess in short what I'm saying is it would be useful that if a component has both a background painter and highlighter the highligher should let the painter deal with painting the highlight. In this way the painter can paint the highlight, or do something appropriate which may of course mean ignore the highlight totally!
Steve