Running on Java 22-ea+27-2262 (Preview)
Home of The JavaSpecialists' Newsletter

019Finding Lost Frames

Author: Dr. Heinz M. KabutzDate: 2001-05-10Java Version: 1.2Category: GUI
 

Abstract: We keep a list of created Frame instances handy, so that we can find them again when we create Dialogs. This prevents ownerless modal Dialogs from causing issues.

 

Welcome to the 19th issue of The Java(tm) Specialists' Newsletter. This newsletter is my contribution to advancing Java skills, and is meant as an informative, advanced newsletter that hopefully will tell you things you won't find in your average newsletter. Please let me know when my content becomes too ordinary or my style too stolid.

Thanks to all those of you who responded to last week's question, there were some interesting opinions flying around, seems like the real reasons why people go/come/stay in places is because of relationships and friendships, with money, technology, etc. only being secondary. With apologies to my readers from the erstwhile Soviet Union, it seems that was quite a well-known fact to the Politburo, but perhaps I've read too many spy stories.

javaspecialists.teachable.com: Please visit our new self-study course catalog to see how you can upskill your Java knowledge.

Finding Lost Frames

Something that I have encountered in some almost-complete projects, were dialogs that were not bound to frames. When you construct a dialog, you should specify who the owner is, which is either a frame or another dialog. It is, however, also possible to specify "null" as the owner, which causes very irritating problems. In MS Windows, if a modal dialog does not have an owner, and you have moved away from it, for example if you quickly switched to Outlook while waiting for it to start up, the only way to get back to the dialog is by using ALT+Tab. If you click on the frame icon on the toolbar, you will get just the frame, not the dialog. Clicking on the frame will cause a beep and that's all.

A few months ago, I asked myself the question: Is there a way in which we can find a frame that has already been created?

One of my first newsletters showed a GlobalHotkeyManager that allowed you to install your own event queue into the AWT, letting you catch any events that occur, before ANY other components get hold of them. Why don't we use the concept to catch Window events and then use those events to remember which frames are available?

The problem with the GlobalHotkeyManager, was that it only allowed exactly one event catcher to be present at a time. It is therefore only safe to use if none of the libraries you use link in a similar event queue. An alternative, suggested by F.S., was to register ourselves as a listener to the main AWT event system by calling Toolkit.getDefaultToolkit().addAWTEventListener().

Each time a window is activated, we grap the handle and add it to our list of frames that we know about. We can then write a method called "lookupFrame(String title)" which goes through the list and returns the first frame that we find with the specified title.

//: FrameLookup.java
import javax.swing.*;
import java.awt.*;
import java.awt.event.*;
import java.util.*;

public class FrameLookup {
  private final Collection frames = new LinkedList();
  // Singleton Pattern
  private static final FrameLookup instance = new FrameLookup();
  public static FrameLookup getInstance() {
    return instance;
  }
  private FrameLookup() {
    Toolkit.getDefaultToolkit().addAWTEventListener(
      new AWTEventListener() {
        public void eventDispatched(AWTEvent event) {
          System.out.println("Event Dispatched : " + event);
          if (event.getID() == WindowEvent.WINDOW_ACTIVATED) {
            if (event.getSource() instanceof Frame) {
              synchronized(frames) {
                frames.add(event.getSource());
              }
            }
          }
        }
      }, AWTEvent.WINDOW_EVENT_MASK);
  }
  public Frame lookupFrame(String title) {
    synchronized(frames) {
      Iterator it = frames.iterator();
      while(it.hasNext()) {
        Frame frame = (Frame)it.next();
        if (frame.getTitle().equals(title)) return frame;
      }
    }
    return null;
  }
}

I can now write a test program that creates a frame, forgets the handle, and then creates a dialog and uses the FrameLookup class to find the correct frame to use as owner.

//: FrameLookupTest.java
import javax.swing.*;
import java.awt.*;

public class FrameLookupTest {
  private static final String SWING_FRAME_TITLE = "Swing Frame";
  private static final String AWT_FRAME_TITLE = "AWT Frame";
  private static final String SWING_DIALOG_TITLE = "Swing Dialog";

  public static void main(String[] args) {
    FrameLookup framer = FrameLookup.getInstance();
    makeFrame();

    // we can find visible frame by using our FrameLookup utility
    System.out.println("Frame is " +
      FrameLookup.getInstance().lookupFrame(SWING_FRAME_TITLE));

    makeDialog();
  }

  private static void makeFrame() {
    JFrame frame = new JFrame(SWING_FRAME_TITLE);
    frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    frame.setSize(300, 300);
    frame.show();
  }

  private static void makeDialog() {
    // we can bind our JDialog to the Frame
    JDialog dialog = new JDialog(
      FrameLookup.getInstance().lookupFrame(SWING_FRAME_TITLE),
      SWING_DIALOG_TITLE, true);
    dialog.setSize(400, 100);
    dialog.show();
  }
}

This is great; we can discover the correct frame as owner, just by knowing its title! There are some minor problems, such as the fact that there is a racing condition involved. It can happen that we request to find the frame before it has been activated or shown, thereby our lookupFrame() method would return "null". Big Oooops. Our situation is now worse than before, as such intermittent failings are MUCH harder to find. Let's also not forget that the title of a frame does not have to be unique.

When I was preparing this newsletter, I got distracted in that I tried to reproduce the Swing deadlock problem (which I didn't manage :(. While I was looking through the source code of JFrame/Frame/Window/Container/Component, I happened upon the method Frame[] java.awt.Frame.getFrames(), which Sun added in the JDK 1.2, according to the @version tag. Is it just me, or have I been reading the wrong publications, that don't tell me about these features? Please, if you have heard of Frame.getFrames(), send me an email.

Anyway, with my newly acquired knowledge, I ran off and wrote a second version of the FrameLookup class that looks like this, and sorts out the racing condition problem:

//: FrameLookup.java take 2
import java.awt.*;
public class FrameLookup {
  // Singleton Pattern
  private static final FrameLookup instance = new FrameLookup();
  public static FrameLookup getInstance() {
    return instance;
  }
  private FrameLookup() { }
  public Frame lookupFrame(String title) {
    Frame[] frames = Frame.getFrames();
    for (int i=0; i<frames.length; i++) {
      if (frames[i].getTitle().equals(title))
        return frames[i];
    }
    return null;
  }
}

We still have the problem that titles alone could be ambigious, but the getFrames() method is definitely the correct way to find a Frame if you need to.

Until next week, and please remember that the more people read this newsletter each week, the more corporate time I can waste collectively, currently I'm wasting about 2 man-months of your development time each week. i.e. please keep on forwarding these newsletters to friends and colleagues who use Java ;-)

Heinz

 

Comments

We are always happy to receive comments from our readers. Feel free to send me a comment via email or discuss the newsletter in our JavaSpecialists Slack Channel (Get an invite here)

When you load these comments, you'll be connected to Disqus. Privacy Statement.

Related Articles

Browse the Newsletter Archive

About the Author

Heinz Kabutz Java Conference Speaker

Java Champion, author of the Javaspecialists Newsletter, conference speaking regular... About Heinz

Superpack '23

Superpack '23 Our entire Java Specialists Training in one huge bundle more...

Free Java Book

Dynamic Proxies in Java Book
Java Training

We deliver relevant courses, by top Java developers to produce more resourceful and efficient programmers within their organisations.

Java Consulting

We can help make your Java application run faster and trouble-shoot concurrency and performance bugs...