Using swing components subclasses without palette

In Swing, often happens, that the custom behaviour to the
standard components is added by subclassing a component.

Often the change is small, and does not deserve the new
public component (that may result in a palette candidate);
it is often realized as inner class or anonymous class.

Consider the following anonymous text field subclass
example, that delegates the paintComponent:

JTextField jtf = new JTextField() {

/** custom paint */
protected void paintComponent(Graphics g) {
// invoke external custom paint ....
ComponentPainter.paint(this, g);
}
};

Currently the UI designer likes to instantiate the
components itself in the $$$setupUI$$$() method.

I was wandering if the simple non null check could be
added to the code gen before creating the component.
This will keep the compatibilty and offer support for
the request.

Note, I'm not loking about extending the designer palette
with the new components.

Thanks,
em

17 comments
Comment actions Permalink

+1, it seems to be an elegant and simple resolution to use self defined subclasses.

0
Comment actions Permalink

-1
method $$$setupUI$$$() called from static init (clinit) method. Eq before any constructors was called (init), so checking for null reference will be always false.

But, you give a good idea. UIDesigner must have ability to plug from standard Swing implementation to derived custom implementation.

For example. Put under for component from standard toolbar component, e.q. javax.swing.JTextField. Second, right click on JTextField component and choose all extendings of JTextField in project.

It better to implement in current UIDesigner model, and you can use it already - just edit XML file and put your ouw class instead of javax.swing.* in *.form file.

This solution will work only for non anonimous classes.

Thanks!

0
Comment actions Permalink

Check the code please....the $$$setupUI$$$() is invoked in dynamic initializer.

One of the important points of this is to not crowd/manage the component palette for each component that contains that kind fo specialization.

em

0
Comment actions Permalink

Yes, you are right method called from dinamic init, sorry, put my words back :)

I still not agree with you about component initialization by user side (not by UIDesigner code), but from other point, i have not good idea to explain my apprehension about it...

For example, code:

Will pass to $$$setupUI$$$ method with initialized "root" local variable (new JPanel() will called before $$$setupUI$$$).
Now look at this sample:

Here method $$$setupUI$$$ will catch uninitialized "root" local variable (root = null).

This can be point of troubles i guess. But if UIDesigner will guarantied call $$$setupUI$$$ after all field initialized, then your solution may be used! :)

In any case, solution about i said, is:

  • UIDesigner always init all componentent in form.

  • UIDesigner used standard component in palette

  • UIDesigner have ability to change implementation class of any components. For example, if you have your ouw implementation og JPanel, and you want to have it on form, you do:

  • Put on form JPanle and place it to position

  • Right click on it, and change implementation class from javax.swing.JPanel to org.my.JPanel or something else.

  • Bind this component to class field.


This can save the safe field initializing.

Thanks!

0
Comment actions Permalink

at least, the current source code generator always put the init code at the last of ur code :). and i think this check and init method is simple and is good to prevent component pallete from too crowded. many times i just want to change little part of standard behaviors, and i don't want bothering to install the sub component.

0
Comment actions Permalink

For example, code:

   private JPanel root = new JPanel();
>   {
>     $$$setupUI$$$();
>   }
> ]]>

Will pass to $$$setupUI$$$ method with initialized
"root" local variable (new JPanel() will called
before $$$setupUI$$$).
Now look at this sample:

   {
>     $$$setupUI$$$();
>   }
>   private JPanel root = new JPanel();
> ]]>

Here method $$$setupUI$$$ will catch uninitialized
"root" local variable (root = null).


I'm not sure if I was clear. The JPanel instance will
be initialized in the $$$setupUI$$$(); if it is null.

That is, the code in $$$setupUI$$$(); looks like:

Basically I suggested to include the 'if' and nothing else.

In any case, solution about i said, is:

  • UIDesigner always init all componentent in form.

  • UIDesigner used standard component in palette

  • UIDesigner have ability to change implementation

class of any components. For example, if you have
your ouw implementation og JPanel, and you want to
have it on form, you do:

  • Put on form JPanle and place it to position

  • Right click on it, and change implementation class

from javax.swing.JPanel to org.my.JPanel or something
else.

  • Bind this component to class field.


I' familiar with what you suggest, thanks. I have evalated the existing options before submitting the request, and the palette modifying is too big hammer
for this simple task imho.

Best,
em

0
Comment actions Permalink

Hi,

Maybe i'm wrong, but code reformat can reorange fields and method arangements.

0
Comment actions Permalink

Including "if" to initializing will not guarantiee you that variable initializaed successfully.

Here variable root instance of MyPanel, but in follow code not:

Now root instance of JPanel...

I think, that UIDesigner must know about real implementation class.

0
Comment actions Permalink

Including "if" to initializing will not guarantiee
you that variable initializaed successfully.


It is not clear why not though.

We just get the opportunity to instantiate the component
before the $$$setupUI$$$();, that is

for example.

On contrary, if the component has not been initialized before then the $$$setupUI$$$() will instantiate it with
whatever $$$setupUI$$$() does, that is

.

I think, that UIDesigner must know about real
implementation class.


Not in this case. By simply subclassing th expected type
(JPanel) we conform to the public interface and that is
all. There are no specific properties that we want to ask
the UI designer to manage for example (which would be a
good case for ading it to a palette).

It is actually an example of what is known as "Liskov Substitution Principle" in OO design.


Best
em

0
Comment actions Permalink

This exactly i was said :)

There only two ways that UIDesigner can do. If UIDesigner know only about interface class, then it can't initialize it. Otherwize, if UIDesigner want to initialize variable, then it must know about implementation.

So, i think, that it must be setted by configuration of UIDesigner. Something like "Use automatic initialization".

In any case $$$setupUI$$$ must be safe for nulls in references.

Thanks!

0
Comment actions Permalink

Don't want to sound obstinant ... but I think we are
not talking exactly about the same thing... read on.

If UIDesigner know only about interface class, then
it can't initialize it.


Important difference here. It can. Here is how. The component is declared as :

and this is how UI designer sees the component. Nothing
more.
Then the developer can specify:

.
But if he chooses not to, the result is


done in the code gen section ($$$setupUI$$$).

In any case $$$setupUI$$$ must be safe for nulls in
references.


Agreed, and that is why my original suggestion was
suggesting the non null check added to the codegen part.
And that simple check actually enables the whole feature.


Best,
em

0
Comment actions Permalink

I agree. But not for:

But if he chooses not to, the result is


done in the code gen section ($$$setupUI$$$).

If developer not initialized variable, then UIDesigner will not try
initialize it but itself, just throw IllegalStateException exception.

Thanks!

"emil" <no_reply@jetbrains.com> wrote in message
news:15039626.1073881755025.JavaMail.itn@is.intellij.net...

Don't want to sound obstinant ... but I think we are
not talking exactly about the same thing... read on.

>

If UIDesigner know only about interface class, then
it can't initialize it.

>

Important difference here. It can. Here is how. The component is declared

as :

and this is how UI designer sees the component. Nothing
more.
Then the developer can specify:


.
But if he chooses not to, the result is


done in the code gen section ($$$setupUI$$$).

>

In any case $$$setupUI$$$ must be safe for nulls in
references.

>

Agreed, and that is why my original suggestion was
suggesting the non null check added to the codegen part.
And that simple check actually enables the whole feature.

>
>

Best,
em

>
>


0
Comment actions Permalink

I agree. But not for:

But if he chooses not to, the result is

 panel = new JPanel();
> ]]>

done in the code gen section ($$$setupUI$$$).

If developer not initialized variable, then
UIDesigner will not try
initialize it but itself, just throw
IllegalStateException exception.


That is what the change request is about. To add the codegen section in $$$setupUI$$$ that contains :

Then everything is safe.

best,
em

0
Comment actions Permalink

Then everything is safe.


Why code:

Is not safe?

The code above more safe that try initialize variable by default
constructor, i guess.
Thanks!


0
Comment actions Permalink
 if (panel == null) {
>   throw new IllegalStateException();
> }
> ]]>

is not safe?

The code above more safe that try initialize variable
by default
constructor, i guess.


This is where we don't agree I'm afraid. It is important
to preserve the default behaviour, and I don't think
that there is a need for a special indicators (do it
this or that way).

Simply, there is a default and overriden behaviour. It is a very common concept.

best,
em






0
Comment actions Permalink

Yes, now i get it :)
So, we need someone to solve our dispute! :)

Unfortunaly, we think differently...
Thanks!

0
Comment actions Permalink

Fortunately you think different ;)

0

Please sign in to leave a comment.