The Source for Java Technology Collaboration
User: Password:



Alexander Potochkin

Alexander Potochkin's Blog

TabComponents in action

Posted by alexfromsun on November 09, 2005 at 10:51 AM | Comments (7)

It's been a lot of publications about adding "close" button to a tabbedPane, all solutions suggested are really inventive and not easy to find. But we are gonna talk about Mustang "tabComponents feature" because it is the most preferable and clear solution for JTabbedPane customizing.

Since 1.6 three new methods added to JTabbedPane:

we can put a component to a tab with help of
public void setTabComponentAt(int index, Component component)

get this component with
public Component getTabComponentAt(int index)

and test if a component is a tabComponent for this JTabbedPane with
public int indexOfTabComponent(Component tabComponent)

With this three methods we can enrich a JTabbedPane with comboboxes, multiple labels or whatever we want.
Remember that JTabbedPane's tab area is not a real component, it is just an image so to insert a component there we can can draw a fake component in addition to the existing tab's title (it was the only solution before Mustang) or set our own tabComponent which can draw title and icon and contain any other additional components.

Please download source files and go on.

First, let's check how we can add the most wanted “close” buttons to a JTabbedPane

TabComponent with a “close” button

(source files in the blog.test1 package)


I sublcassed JPanel and added there JLabel to show tab's title and a customized button which can close this tab – and that's it !

Here how it looks:


Notice that we use a real JButton here so we can set a tooltip, attach an ActionListener and customise it in any ways

The only new thing is the close button's actionListener:

        public void actionPerformed(ActionEvent e) {
            int i = pane.indexOfTabComponent(ButtonTabComponent.this);
            if (i != -1) {
                pane.remove(i);
            }
        }

When we click to this button we find the index of the tab this button belongs to and close the tab.

The only possible problem is that this tabComponent doesn't respect actual JTabbedPane's titles so if we remove all tabComponents
(with help of "Options" menu from the test) we'll see:

JTabbedPane without tabComponents

Notice that actual tab's titles looks like tab1 not like tabComponent1.

In the next example we'll easily create better tabComponent which can show the actual titles.

JRadioButton as a tabComponent

(source files in the blog.test2 package)


Let's say we don't like JTabbedPane's focus rendering and want to replace it with something else.
For example we like JRadioButtons and want them to render font and focus for the tabs.
We can easily achieve that:


With this code:

        JRadioButton button = new JRadioButton() {
            //This way we always have up-to-date tab's title 
            public String getText() {
                int i = pane.indexOfTabComponent(this);
                if (i != -1) {
                    return pane.getTitleAt(i);
                }
                return null;
            }
        };

our radioButton will alway show the actual tab's title.

We only need to add one listener to radioButtons to select a tab when we select a JRadioButton
and one listener to JTabbedPane to do the opposite - select proper radioButton when we select a tab.

Crazy tabComponent with two icons

(source files in the blog.test3 package)


It is possible to show not only a title from a tab, but an icon as well.
Just for fun I created a big tabComponent which shows a title between to identical icons:


if we remove all tabComponents we'll see that actual title and actual icon are used:


We find the acual icon just like we find titles for the previous example

Conclusion

TabComponents make it possible to customise JTabbedPane component quite easily,
please try the latest Mustang build and create your own tabComponents !

let me give you some recommendations

  1. Keep in mind that tabs are not a real components just an image, so it is good idea to use components with setOpaque(false) to see tab's decorations underneath.
  2. Use proper spacing around your tabComponents, because big opaque component may overlap tab's decorations.
  3. To be on the safe side, test your tabComponents for all LaF's you
    use in your application (for WRAP_TAB_LAYOUT and SCROLL_TAB_LAYOUT).
  4. If you need to add a listener to your tabComponents, create the only instance of a listener and share it between all tabComponents
  5. Remember that only components without MouseListeners and MouseMotionListeners are transparent for mouse events. To be on the safe side use additional mouseListener which will select a proper tab when you click on tabComponent.
    For more information about that see my previous blog

Thanks
Alex


Bookmark blog post: del.icio.us del.icio.us Digg Digg DZone DZone Furl Furl Reddit Reddit
Comments
Comments are listed in date ascending order (oldest first) | Post Comment

  • As I am building an image and animation editor in swing, this is what fullfill my needs. Now I can implement easy to close/remove an image from the animation sequenz. Also I will have a small preview of the inactive nonvisible noneditable images in the same time.
    This will make the animation option much smarter to use.
    This will be helpfull even for the skeletonbuilder in my appliction.

    Posted by: malte_kosian on November 10, 2005 at 04:08 AM

  • As a workaround for java 1.4 or 1.5 users, vldocking provides support for JTabbedPanes with multiple buttons in tabs.

    I've done it by creating an icon that mimics the contents of the tab, including the label. It can support any number of buttons, and also mimics their rollover and pressed state.

    Too bad real components in tabs is only part of jdk 1.6, a backport to 1.5 would really be appreciated !

    Lilian Chamontin, VLSolutions

    Posted by: vlsolutions on November 10, 2005 at 05:01 AM

  • Hello Lilian
    It would involve API change so I doubt we could backport it,
    anyway, I am happy that we did this feature for Mustang

    Thanks
    Alex

    Posted by: alexfromsun on November 14, 2005 at 08:53 AM

  • So can you make all your tab components draggable and all your JTabbedPanes drop targets and drag tabs from one window to another, like Photoshop lets you do with its palettes?

    Posted by: torgen on August 24, 2006 at 10:44 AM

  • Hello torgen

    This feature is about adding any components you need
    there are no any particular tabComponents implemented in JDK 6.0
    so if you need draggable tabComponents, you can implement them and set to the JTabbedPane

    Thanks
    alexp

    Posted by: alexfromsun on August 25, 2006 at 02:18 AM

  • Alex,

    I found that if I added a JPanel that contained an icon, label and exit button the JPanel would be the default L&F background color and not get the selected color to show Tab selection. To fix this all I had to do was add this line in my JPanel constructor:

    setOpaque(false);


    Regards


    Posted by: cupofjoe on October 16, 2007 at 11:52 AM

  • Hello Cupofjoe
    Thanks for the comment
    I also make the TabComponent from the source files for this blog non-opaque
    Best regards
    alexp


    Posted by: alexfromsun on October 17, 2007 at 05:51 AM





Powered by
Movable Type 3.01D
 Feed java.net RSS Feeds