Dynamic Debugging with Swing

Swing is the most powerful GUI toolkit I have tried until now. QT, wxWidgets, Windows Forms, Tkinter, MFC, etc. have qualities but none offers such a control over the components. Such a power has a drawback though, Swing is complicated and sometimes hard to debug. Besides Jan Böesenberg's cool hack (please do your best to release it :) and JGoodies debug mode, I don't know any tool to debug a Swing UI. Rejoice my friends, Swing itself can help if you don't mind hacking a bit and using somewhat crude tools.

When working on my Net Video Watch project, I felt the need to easily spot the borders set on the components of the UI. I could have added a custom border to each of them but it would have been painful. I then thought of a new cool use for the glass pane but I wanted to try something else. And it was anyway restricted to a single frame. I finally chose to use an AWTEventListener to catch the application mouse events. You should download the source code of my work and add the following lines to your application:

import java.awt.Toolkit;
import java.awt.event.AWTEvent;
import org.progx.swing.debug.DebugEventListener;
// ...
Toolkit kit = Toolkit.getDefaultToolkit();
kit.addAWTEventListener(new DebugEventListener(), AWTEvent.MOUSE_EVENT_MASK);

Now launch your application and move the mouse over some components. You should see something a green layer on top of the component's border, as in the following screenshot:

The effect is better shown here, when the mouse is over a button:

The trick I used is very simple and pretty straightforward. The basic idea is to replace the component which emitted a mouse enter event by a custom border. When the mouse exits the component, the old border is put back in place:

public class DebugEventListener implements AWTEventListener {
  public void eventDispatched(AWTEvent event) {
    Object o = event.getSource();
    if (o instanceof JComponent) {
      JComponent source = (JComponent) o;
      Border border = source.getBorder();

      switch (event.getID()) {
        case MouseEvent.MOUSE_ENTERED:
          if (border != null) {
            source.setBorder(new DebugBorder(border));
        case MouseEvent.MOUSE_EXITED:
          if (border != null && border instanceof DebugBorder) {
            source.setBorder(((DebugBorder) border).getDelegate());

As you can see, the custom component knows the old border which is used as a delegate for the various methods of the Border interface. The method paintBorder() contains some code to draw the translucent green patch over the original border.

The code shown here is very simple and lacks a lot of things. It cannot, for instance, substitute the border of panels which could be done by listening to the mouse motion events. It is interesting though to see that we can easily add runtime debugging features to Swing with little efforts. I have other ideas of (more) useful debugging behaviors but I don't have the time to implement them now. Stay tuned, we never know ;-)

Comments are closed.