93

当遥控机制激活应用程序中的某些内容时,我们需要将 Java 应用程序置于前台。

为了实现这一点,我们在代表我们应用程序框架的类的被调用方法中实现了JFrame以下实现(a的扩展):

setVisible(true);
toFront();

在 Windows XP 下,第一次调用它可以工作,第二次只有任务栏中的选项卡闪烁,框架不再出现在前面。Win2k 也一样。在 Vista 上它似乎工作正常。

你有什么想法?

4

11 回答 11

70

一个可能的解决方案是:

java.awt.EventQueue.invokeLater(new Runnable() {
    @Override
    public void run() {
        myFrame.toFront();
        myFrame.repaint();
    }
});
于 2008-12-22T21:09:37.293 回答
35

JFrame在 Ubuntu(Java 1.6.0_10)下将 a 放在前面时我遇到了同样的问题。我可以解决它的唯一方法是提供一个WindowListener. 具体来说,我必须将 my 设置为在被调用JFrame时始终保持在最前面,并为.toFront()windowDeactivatedsetAlwaysOnTop(false)


因此,这是可以放入 base 的代码,JFrame用于派生所有应用程序框架。

@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) {
      toFront();
  }
}

@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);
}

每当您的框架应该被显示或带到前面调用时frame.setVisible(true)

自从我搬到 Ubuntu 9.04 以来,似乎没有必要使用WindowListenerfor 调用super.setAlwaysOnTop(false)- 正如可以观察到的那样;此代码已移至方法toFront()setVisible().

请注意,该方法setVisible()应始终在 EDT 上调用。

于 2009-02-27T19:01:40.800 回答
23

Windows 具有防止 Windows 窃取焦点的功能;相反,它会闪烁任务栏图标。在 XP 中,默认情况下它是打开的(我见过的唯一改变它的地方是使用 TweakUI,但在某处有一个注册表设置)。在 Vista 中,他们可能已经更改了默认设置和/或将其作为用户可访问的设置与开箱即用的 UI 一起公开。

自 Windows 2K 以来,防止窗口强迫自己到前面并集中注意力是一项功能(我对此表示感谢)。

也就是说,我有一个小的 Java 应用程序用来提醒我在工作时记录我的活动,它每 30 分钟将自己设为活动窗口(当然是可配置的)。它始终在 Windows XP 下始终如一地工作,并且从不闪烁标题栏窗口。它使用以下代码,作为定时器事件触发的结果在 UI 线程中调用:

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

(如果最小化第一行会恢复......实际上如果最大化它也会恢复它,但我从来没有这样)。

虽然我通常将这个应用程序最小化,但通常它只是在我的文本编辑器后面。而且,就像我说的,它总是有效的。

我确实知道你的问题可能是什么——也许你有 setVisible() 调用的竞争条件。toFront() 可能无效,除非在调用它时实际显示了窗口;我之前在 requestFocus() 上遇到过这个问题。您可能需要将 toFront() 调用放在窗口激活事件的 UI 侦听器中。

2014-09-07:在某个时间点,上述代码停止工作,可能是在 Java 6 或 7 中。经过一些调查和实验后,我不得不更新代码以覆盖窗口的toFront方法(结合修改后的代码从什么上面):

setVisible(true);
toFront();
requestFocus();
repaint();

...

public @Override void toFront() {
    int sta = super.getExtendedState() & ~JFrame.ICONIFIED & JFrame.NORMAL;

    super.setExtendedState(sta);
    super.setAlwaysOnTop(true);
    super.toFront();
    super.requestFocus();
    super.setAlwaysOnTop(false);
}

从 Java 8_20 开始,这段代码似乎运行良好。

于 2008-11-22T03:25:00.563 回答
12

这是一种真正有效的方法(在 Windows Vista 上测试):D

   frame.setExtendedState(JFrame.ICONIFIED);
   frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);

fullscreen 变量指示您希望应用程序全屏运行还是窗口化运行。

这不会使任务栏闪烁,而是可靠地将窗口置于前面。

于 2011-09-15T18:33:32.073 回答
5

Hj,在 Fedora KDE 14 中,你的所有方法都不适用于我。我有一个肮脏的方法可以把一个窗口放在前面,而我们正在等待 Oracle 解决这个问题。

import java.awt.MouseInfo;
import java.awt.Point;
import java.awt.Robot;
import java.awt.event.InputEvent;

public class FrameMain extends javax.swing.JFrame {

  //...
  private final javax.swing.JFrame mainFrame = this;

  private void toggleVisible() {
    setVisible(!isVisible());
    if (isVisible()) {
      toFront();
      requestFocus();
      setAlwaysOnTop(true);
      try {
        //remember the last location of mouse
        final Point oldMouseLocation = MouseInfo.getPointerInfo().getLocation();

        //simulate a mouse click on title bar of window
        Robot robot = new Robot();
        robot.mouseMove(mainFrame.getX() + 100, mainFrame.getY() + 5);
        robot.mousePress(InputEvent.BUTTON1_DOWN_MASK);
        robot.mouseRelease(InputEvent.BUTTON1_DOWN_MASK);

        //move mouse to old location
        robot.mouseMove((int) oldMouseLocation.getX(), (int) oldMouseLocation.getY());
      } catch (Exception ex) {
        //just ignore exception, or you can handle it as you want
      } finally {
        setAlwaysOnTop(false);
      }
    }
  }

  //...

}

而且,这在我的 Fedora KDE 14 中完美运行 :-)

于 2011-09-13T15:21:51.107 回答
5

我测试了你的答案,只有Stefan Reich 的答案对我有用。虽然我无法将窗口恢复到以前的状态(最大化/正常)。我发现这个突变更好:

view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);

那是setState代替setExtendedState.

于 2012-03-09T13:27:16.780 回答
4

这个简单的方法在 Windows 7 中非常适合我:

    private void BringToFront() {
        java.awt.EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                if(jFrame != null) {
                    jFrame.toFront();
                    jFrame.repaint();
                }
            }
        });
    }
于 2011-05-10T14:38:48.607 回答
3

我发现跨平台没有不一致的最简单方法:

设置可见(假);设置可见(真);

于 2010-11-02T15:41:50.783 回答
2

管理 .toFront() 一个 JFrame 时发生的事情的规则在 windows 和 linux 中是相同的:

-> 如果现有应用程序的窗口当前是焦点窗口,则焦点切换到请求的窗口 -> 如果不是,则窗口仅在任务栏中闪烁

但 :

-> 新窗口自动获得焦点

所以让我们利用它!你想把一个窗口带到前面,怎么做?好 :

  1. 创建一个空的非用途窗口
  2. 展示下
  3. 等待它出现在屏幕上(setVisible 这样做)
  4. 显示时,为您实际想要获得焦点的窗口请求焦点
  5. 隐藏空窗口,销毁它

或者,在 java 代码中:

// unminimize if necessary
this.setExtendedState(this.getExtendedState() & ~JFrame.ICONIFIED);

// don't blame me, blame my upbringing
// or better yet, blame java !
final JFrame newFrame = new JFrame();
newFrame.add(new JLabel("boembabies, is this in front ?"));

newFrame.pack();
newFrame.setVisible(true);
newFrame.toFront();

this.toFront();
this.requestFocus();

// I'm not 100% positive invokeLater is necessary, but it seems to be on
// WinXP. I'd be lying if I said I understand why
SwingUtilities.invokeLater(new Runnable() {
  @Override public void run() {
    newFrame.setVisible(false);
  }
});
于 2011-06-24T15:11:47.593 回答
1

为了避免窗口在隐藏后返回可见时失去焦点,所需要做的是:

setExtendedState(JFrame.NORMAL);

像这样:

defaultItem.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e) {
                showWindow();
                setExtendedState(JFrame.NORMAL);
            }
});
于 2014-12-30T20:55:07.320 回答
0

javadoc 中有许多关于 toFront() 方法的警告,这可能会导致您的问题。

但是我还是猜测一下,当“只有任务栏中的选项卡闪烁”时,应用程序是否已最小化?如果是这样,javadoc 中的以下行可能适用:

“如果此窗口可见,则将此窗口置于最前面,并可能使其成为焦点窗口。”

于 2008-11-21T15:23:00.363 回答