views:

5686

answers:

6

We have a Java-application that needs to be brought to the foreground when a telecontrol mechanism activates something in the application.

In order to get this we have realised in the called method of the Class which represents the Frame of our application (extension of a JFrame) following implementation:

setVisible(true);
toFront();

Under Windows XP this works the first time it is called, on the second time only the tab in the taskbar flashes, the frame doesn't come to the front anymore. Same goes for Win2k. On Vista it seems to work fine.

Anyone ideas?

+1  A: 

There are numerous caveats in the javadoc for the toFront() method which may be causing your problem.

But I'll take a guess anyway, when "only the tab in the taskbar flashes", has the application been minimized? If so the following line from the javadoc may apply:

"If this Window is visible, brings this Window to the front and may make it the focused Window."

bcash
+7  A: 

Windows has the facility to prevent windows from stealing focus; instead it flashes the taskbar icon. In XP it's on by default (the only place I've seen to change it is using TweakUI, but there is a registry setting somewhere). In Vista they may have changed the default and/or exposed it as a user accessible setting with the out-of-the-box UI.

Preventing windows from forcing themselves to the front and taking focus is a feature since Windows 2K (and I, for one, am thankful for it).

EDIT: That said, I have a little Java app I use to remind me to record my activities while working, and it makes itself the active window every 30 minutes (configurable, of course). It always works consistently under Windows XP and never flashes the title bar window. It uses the following code, called in the UI thread as a result of a timer event firing:

if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();

(the first line restores if minimized... actually it would restore it if maximized too, but I never have it so).

While I usually have this app minimized, quite often it's simply behind my text editor. And, like I said, it always works.

EDIT2: I have an idea on what your problem could be - perhaps you have a race condition with the setVisible() call. toFront() may not be valid unless the window is actually displayed when it is called; I have had this problem with requestFocus() before. You may need to put the toFront() call in a UI listener on a window activated event.

Software Monkey
+1 for supporting not allowing windows to steal the focus. I hate when that happens when I'm typing in a document.
Ken Paul
I completely agree with you against stealing focus, but in this precise case the user expects the application to come to the front. But it would uncool to change the registry settings and change the complete windows behavior.
boutta
A: 

possible solution is:

                java.awt.EventQueue.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        myFrame.toFront();
                        myFrame.repaint();
                    }
                });
+7  A: 

I had the same problem with brining a frame to the front under Ubuntu (Java 1.6.0_10). And the only way I could resolve it is by providing a window listener. Specifically, I had to set frame to always stay on top whenever toFront is invoked, and provide windowDeactivated event handler to setAlwaysOnTop(false).

If anyone is interested in a complete code pls leave a comment.


So, here is the code that could be placed into a base frame, which is used to derive all application frames.

@Override
public void setVisible(final boolean visible) {
  // make sure that frame is marked as not disposed if it is asked to be visible
  if (visible) {
      setDisposed(false);
  }
  // let's handle visibility...
  if (!visible || !isVisible()) { // have to check this condition simply because super.setVisible(true) invokes toFront if frame was already visible
      super.setVisible(visible);
  }
  // ...and bring frame to the front.. in a strange and weird way
  if (visible) {
      int state = super.getExtendedState();
      state &= ~JFrame.ICONIFIED;
      super.setExtendedState(state);
      super.setAlwaysOnTop(true);
      super.toFront();
      super.requestFocus();
      super.setAlwaysOnTop(false);
  }
}

@Override
public void toFront() {
  super.setVisible(true);
  int state = super.getExtendedState();
  state &= ~JFrame.ICONIFIED;
  super.setExtendedState(state);
  super.setAlwaysOnTop(true);
  super.toFront();
  super.requestFocus();
  super.setAlwaysOnTop(false);
}

Whenever frame should be displayed or brought to front call frame.setVisible(true).

Since I moved to Ubuntu 9.04 there seems to be no need in having a window listener for invoking super.setAlwaysOnTop(false) -- as can be observed this code was moved to methods toFront and setVisible.

Pls note that method setVisible should always be invoked on EDT.

01es
I'd be interested.
rogerdpack
Worked under all circumstances, so I accepted this one.
boutta
+1 Was very helpful, Thanks!
Virat Kadaru
Thanks!Also related is this question: http://stackoverflow.com/questions/2315560/how-do-you-force-a-java-swt-program-to-move-itself-to-the-foreground
rogerdpack
A: 

to do the same thing in applet mode what should i have to do?

You really should start this up as it's own question if you want to know, instead of sticking it as an answer here.
nilamo