Decorate a JLabel with an aditional Icon

Hi !

My problem is to decorate a JLabel with an aditional Icon then JLabel already have natively.

My aproach was to create a "real decorator" in the classical way : the main idea is to wrap the decorated object into the Decorator pattern,

the Decorator pattern forwards requests to the wrapped object and can perform the new functionality before or after forwarding, or as separate methods.

The code look so:

publicclass JLabelWithAdditionalImageextends JLabel{

JLabel jLabel;//=new JLabel();//the object that is wrapped

int additionalIconStatus;//retain the state of image--1=painted 0=not painted

public JLabelWithAdditionalImage(JLabel pjLabel){

this.jLabel=pjLabel;

}

//the decorator real action

publicvoid paint(java.awt.Graphics g){

super.paint(g);

if (additionalIconStatus==1){

g.fillRect(0, 0, 15,15);

}else{

g.dispose();//clear--scoate toate desenele anterioare.

}

}

// from here I overwrite ALL the JLabel public methods to forward requests to the wrapped object

publicvoid setText(String text){

jLabel.setText(text);

}

.......... and so on, overwrite ALLpublic methods of JLabelclass

The problem is that this aproach seems to not work on JLabel (and maybe on other swing components) because when the decorator is initiated

(so, when new instance of decorator is created), first must be initialized the extended class, wich at initialization - call the OVERWRITTEN method setText

and in this point raise the NullPointerException.

Can you tell me if I can use the wrapped aproach to achieve such a decorator ?

Thank you!

[2612 byte] By [liviudela] at [2007-10-2 10:50:03]
# 1

Decorator pattern decorates an interface and not the implementation.

Since JLabel is an implementing class you don't want to decorate it. Interfaces like TableCellRenderer are good to decorate, as you could return a JLabelWithAdditionalImage instead of a plain JLabel as the cell renderer.

jvaudrya at 2007-7-13 3:07:43 > top of Java-index,Other Topics,Patterns & OO Design...
# 2

I believe that is ideal that a decorator to extend/implement an interface or an abstract class--in this situation all classes wich extend/implement that interface or abstract class can be decorated, but it is not a requirement that a decorator not extend any class.

Quotation from :

http://www.javaworld.com/javaworld/jw-12-2001/jw-1214-designpatterns.html?

:

"

Decorators extend the decorated class (or implement the decorated interface), which lets decorators masquerade as the objects they decorate.

FileReaderfrdr = new FileReader(filename);

LineNumberReader lrdr = new LineNumberReader(frdr);

end Quotation .

So, what I do wrong in my code?

liviudela at 2007-7-13 3:07:43 > top of Java-index,Other Topics,Patterns & OO Design...
# 3
PS: It is evident that FileReader and LineNumberReader are not abstract classes or interfaces, so it is posible to decorate real classes.
liviudela at 2007-7-13 3:07:43 > top of Java-index,Other Topics,Patterns & OO Design...
# 4

> The problem is that this aproach seems to not work on

> JLabel (and maybe on other swing components) because

> when the decorator is initiated

> (so, when new instance of decorator is created),

> first must be initialized the extended class, wich at

> initialization - call the OVERWRITTEN method

> setText

> and in this point raise the NullPointerException.

Classical.

Subclass fields are initialized only after Superclass fields, so if the superclasss constructor calls overridden methods nasty things can happen. But you already got it.

You can correct this by adding null checks in all overridden methods, but yeah, I know, it's a bit inelegant, plus you'll have to call these methods again from your own constructor.

public void setText(String text) {

if (jLabel!=null) {

jLabel.setText(text);

}

}

N.B.: and you cannot use the NullObject pattern either, as jLabel will always be null when the superclass constructor calls the overridden method, even if you initialize jLabel in its field declaration.

> Can you tell me if I can use the wrapped aproach to

> achieve such a decorator ?

Using null checks as above.

Other than that, if you simply need to display two icons within a label, and not dynamically decorate an existing jLabel with a second icon, you don't need to use the Decorator pattern.

You could just as well extend JLabel without wrapping a JLabel instance (and without overriding methods other than paint()),

or maybe even design a new JComponent subclass instead.

So far I don't see what the wrapped jLabel gives you (but I cannot tell from the class alone, it's rather in how you plan other classes to use it).

jdupreza at 2007-7-13 3:07:43 > top of Java-index,Other Topics,Patterns & OO Design...
# 5
Thank you!I'll try it!
liviudela at 2007-7-13 3:07:43 > top of Java-index,Other Topics,Patterns & OO Design...