Skip to main content

Swing in a better world: Compound components

Posted by alexfromsun on September 7, 2011 at 9:13 AM PDT

Swing makes it very easy to control and modify simple components like JLabel or JButton. It gets trickier when you customize a compound component like JTree or JTable. Unlike a simple component, JTable consists of multiple subcomponents like table header, renderer and editor, so actually JTable is not a single component but a container with several descendants.

Imagine that you want to customize a JLabel to change its border when you move the mouse cursor over it. You just add a mouse listener and switch the border there back and forth. Now let's make the task a bit more challenging - you want make the same trick with a JPanel which contains a JButton inside.

import javax.swing.*;
import java.awt.*;
import java.awt.event.*;

public class JPanelTest extends JFrame {
    public JPanelTest() {
        super("JPanel test");
        setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        final JPanel panel = new JPanel();
        add(panel);
       
        panel.addMouseListener(new MouseAdapter() {
            public void mouseEntered(MouseEvent e) {
                panel.setBorder(
                BorderFactory.createLineBorder(Color.GREEN, 5));
            }

            public void mouseExited(MouseEvent e) {
                panel.setBorder(null);
            }
        });
       
        panel.setLayout(new GridLayout(0, 2));
        panel.add(new JButton("JButton"));
       
        setSize(300, 300);
        setLocationRelativeTo(null);
    }

    public static void main(String... args) throws Exception {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new JPanelTest().setVisible(true);
            }
        });
    }
}

 Running this test you will see that when the mouse cursor enters the child button the parent panel receives the mouseExited event and the border is gone.

 

To fix it you should add the same listener to the button and to all of the possible panel's children recursively.
It may sound as a minor problem, but it gets complicated if the hierarachy is changing. In this case you should add this listener to the newly added component and remove it accordingly.

By the way, adding a mouseListener may considerably change the component's behaviour as I illustrated in my very first entry. So implementing a simple animation for a compound component is quite a challenging task in Swing.

Missing API

Compound components is a key part of any GUI toolkit so it is important to support them in a better way. In Swing I am missing a simple solution which would give me a chance to listen for the input events not for a single component but for a component and all its subcomponents. JLayer component added in JDK 7, can catch all the events from its children, but this is a topic for another entry.

This was an entry from the Swing in a better world series

Thanks
alexp

Related Topics >>

Comments

5 years ago you did a little side ...

5 years ago you did a little side project:
http://weblogs.java.net/blog/alexfromsun/archive/2007/11/debug_swing_rep.html

that i think should be packaged into swinghelper's debug jar or similar:
http://swinghelper.java.net/

I also can no longer find it, so i'd request a new link.

Thank you, and good luck with swing redesigning (would be nice to get swing 2.0).

A problem that I often face is the lack of a ...

A problem that I often face is the lack of a consolidated binding architecture. As far as I know, BeansBindng (while adopted in Netbeans ide) is not part of the jdk yet, and the fact that its "ufficial" adoption is continuously delayed (was java 7, but has been delayed. Perhaps will be java 8, but nobody hazards a prediction anymore) seems to indicate that Oracle isn't intrested in that specific binding technology. While we, java developers, try to guess what the binding architecture will be (if there will be one) and many of us implement an home-made one, other developement environes comes with data-bound controls, that are able to connect to a database record out of the box.

For such scenarios I prefer to add a separate MouseListener ...

For such scenarios I prefer to add a separate MouseListener to the subcomponent and to redispatch mouse events. We had a similar blog post in the queue which is now online - see

http://www.jyloo.com/news/?pubId=1315817317000

The mouseListener approach doesn't work for all ...

The mouseListener approach doesn't work for all scenarious,
try to show the frame's glassPane, add a mouseListener to it
and then redispatch the events to the components below it.

Similarly if a component has a transparent panel inside,
adding a mouseListener to it will break the mouseEvents processing

The worst is JComboBox.  I can think of several ...

alexfromsun wrote:
Swing makes it very easy to control and modify simple components like JLabel or JButton. It gets trickier when you customize a compound component like JTree or JTable.

The worst is JComboBox. I can think of several problems with it. It's too bad that Swing issues don't get any attention anymore, especially since JavaFX still is not actually usable for projects with long-term futures.

Hello mcdev1 I can't say that Swing issues don't get any ...

Hello mcdev1

I can't say that Swing issues don't get any attention,
we fix critical bugs and JLayer is a nice addition to JDK 7

Thanks
alexp

The Swing team does great work, but it's fighting a losing ...

The Swing team does great work, but it's fighting a losing battle.

The problem is that Swing is shipped inside the JDK, which mean it has horrible backwards compatibility guarantees to meet.

If Swing was split off from the JDK, the Swing team would be free to ship newer versions without the legacy cruft, enabling it to grow into the toolkit it should be.

Come over and have a look at Apache Pivot (http://pivot.apache.org/) to see how clean GUI toolkit code can be in Java when designing without a legacy burden.

The pivot project looks great! grandinj, are you one of its ...

The pivot project looks great!
grandinj, are you one of its contributors?

Thanks
alexp

 Thanks! Yes, I'm one of the contributors - only in a ...

Thanks!

Yes, I'm one of the contributors - only in a very small way, I do minor bugfixes and some work on the Text components.

The primary committers are Todd Volkert and Greg Brown, and the toolkit is descended from an internal VMWare project.

You're welcome to contact me at noelgrandin@gmail.com if you want any more information.