Skip to main content

Easily Use Custom Swing Components with Matisse

Posted by joshy on February 7, 2006 at 3:08 PM PST

I know it's been quite a while since I've written anything. I've been busy with quite a few project and I'll have some cool stuff to share soon. In the meantime I thought I'd show you an interesting tidbit I discovered in Matisse and Netbeans.

I've recently begun using Matisse for all of my GUI building tasks and overall I'm pretty pleased. I can quickly whip up dialog boxes and basic layouts very easily. However, I often use custom components and it's not easy to integrate them with Matisse. Sure, I could package my components up as full Java Beans and install them in the palette, but that's a whole lot of work for a single instance or two. I don't really want to have Matisse create the component for me, I just want the ability to use it's layout.

In the past I have created a panel with a zero width border and then put my custom components inside that. This will work most of the time but it still doesn't feel quite right. I'd rather have Matisse lay out my real component. I can't quite do that but I have found a nice little workaround that's pretty close.

The property palette has three tabs: Properties, Events, and Code. On the code tab there is a property (probably the last one) called Custom Creation Code. This property will let you use a custom constructor and initialization code. If you leave it blank then Matisse will generate something like "new JButton()" but you can override it to use your own code, as long as the result is some compatible class.

This may all sound a bit confusing so lets go with an example. I have a custom JButton subclass that I use for selecting colors. It's just like the normal JButton except it overrides the paintComponent() method to draw a box with the current background color. When you click on the button it will open a JColorChooser dialog to select a new color. Simple enough and not something I'd want to add to the designer palette. Instead I'll use the custom creation code.

I start by creating a normal JButton in the designer like this:

a custom JButton in design mode

Then I go to the Custom Creation Code property in the code tab of the Properties palette and type in: new ColorSelectionButton(); Note that I didn't type in the jButton1 = part.

the Custom Creation Code property

If I switch to code view and look at the generated code I can see this.


    private void initComponents() {
        jButton1 = new ColorSelectionButton();

        jButton1.setText("jButton1");

Matisse Generated Code

Then when I run my program it will look like this:

Running Program

This system works great and I think I'm going to start using it from now on. It does have a couple of downsides though:

  1. You can only use the parent class of your component. Your custom component will be cast down to a standard one so if you use a custom JButton then you must use a JButton in the designer rather than, say, a JLabel. As a consequence..
  2. You can't use direct subclasses of JComponent because there is no JComponent in the standard palette. Most of the time this is fine (I usually subclass JButton or JPanel), but it might be a problem depending on your code.
  3. Your preview in design mode won't match the running application. Matisse does a very good job of making design and runtime views match up, but using this hack defeats Matisse's efforts. In my example I see my custom button at runtime but still get the standard button in the design view.

So it's not perfect, but for most cases I have found it to be quite acceptable and plan to use this technique more in the future.


Update

Approximately 4.8 milliseconds after I posted this gfx informed me that Netbeans actually has a way to add components to the palette without creating a full Java bean. :) You can use the Palette Manager to add any public component class to the palette. *sigh*. Anyway, using the palette only works if you have a public class with no-arg constructor, so my technique is still useful if you want to use a special constructor or an anonymous inline subclass.

Enjoy!

Related Topics >>