Java 如何把窗户放在前面?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/309023/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to bring a window to the front?
提问by boutta
We have a Java application that needs to be brought to the foreground when a telecontrol mechanism activates something in the application.
我们有一个 Java 应用程序,需要在遥控机制激活应用程序中的某些内容时将其置于前台。
In order to get this, we have realized in the called method of the class which represents the frame of our application (extension of a JFrame
) following implementation:
为了实现这一点,我们在代表我们应用程序框架的类的被调用方法中实现了JFrame
以下实现(a 的扩展):
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.
在 Windows XP 下,这在第一次被调用时起作用,第二次只有任务栏中的选项卡闪烁,框架不再出现在前面。Win2k 也是如此。在 Vista 上它似乎工作正常。
Do you have any ideas?
你有什么想法?
采纳答案by Lawrence Dol
A possible solution is:
一个可能的解决方案是:
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
回答by Brendan Cashman
There are numerous caveatsin the javadoc for the toFront() method which may be causing your problem.
javadoc 中有许多关于 toFront() 方法的警告,这些警告可能会导致您的问题。
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:
但无论如何我都会猜测,当“只有任务栏中的选项卡闪烁”时,应用程序是否已最小化?如果是这样,javadoc 中的以下行可能适用:
"If this Window is visible, brings this Window to the front and may make it the focused Window."
“如果此 Window 可见,则将此 Window 置于最前面并使其成为焦点窗口。”
回答by Lawrence Dol
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.
Windows 具有防止 Windows 窃取焦点的功能;相反,它会闪烁任务栏图标。在 XP 中,它默认开启(我见过的唯一改变它的地方是使用 TweakUI,但某处有一个注册表设置)。在 Vista 中,他们可能已经更改了默认设置和/或将其公开为具有开箱即用 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).
自 Windows 2K 以来,防止窗口将自己逼到最前面并获得焦点是一项功能(对于我而言,我对此表示感谢)。
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:
也就是说,我有一个小 Java 应用程序,我用它来提醒我在工作时记录我的活动,它每 30 分钟使自己成为活动窗口(当然是可配置的)。它始终在 Windows XP 下始终如一地工作,并且从不闪烁标题栏窗口。它使用以下代码,作为定时器事件触发的结果在 UI 线程中调用:
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.
虽然我通常将这个应用程序最小化,但通常它只是在我的文本编辑器后面。而且,就像我说的,它总是有效的。
I do 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.
我确实知道您的问题可能是什么 - 也许您在 setVisible() 调用中存在竞争条件。toFront() 可能无效,除非在调用时实际显示窗口;我之前在 requestFocus() 上遇到过这个问题。您可能需要将 toFront() 调用放在窗口激活事件的 UI 侦听器中。
2014-09-07:At some point in time the above code stopped working, perhaps at Java 6 or 7. After some investigation and experimentation I had to update the code to override the window's toFront
method do this (in conjunction with modified code from what is above):
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);
}
As of Java 8_20, this code seems to be working fine.
从 Java 8_20 开始,这段代码似乎运行良好。
回答by 01es
I had the same problem with bringing a JFrame
to the front under Ubuntu (Java 1.6.0_10). And the only way I could resolve it is by providing a WindowListener
. Specifically, I had to set my JFrame
to always stay on top whenever toFront()
is invoked, and provide windowDeactivated
event handler to setAlwaysOnTop(false)
.
我JFrame
在 Ubuntu (Java 1.6.0_10) 下将 a带到前面时遇到了同样的问题。我可以解决它的唯一方法是提供一个WindowListener
. 具体来说,我必须将 my 设置JFrame
为在toFront()
被调用时始终保持在最前面,并将windowDeactivated
事件处理程序提供给setAlwaysOnTop(false)
.
So, here is the code that could be placed into a base JFrame
, which is used to derive all application frames.
所以,这里是可以放置到 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);
}
Whenever your frame should be displayed or brought to front call frame.setVisible(true)
.
每当您的框架应该显示或带到前台时frame.setVisible(true)
。
Since I moved to Ubuntu 9.04 there seems to be no need in having a WindowListener
for invoking super.setAlwaysOnTop(false)
-- as can be observed; this code was moved to the methods toFront()
and setVisible()
.
自从我转移到 Ubuntu 9.04 后,似乎没有必要使用WindowListener
for 调用super.setAlwaysOnTop(false)
——正如可以观察到的那样;此代码已移至方法toFront()
和setVisible()
.
Please note that method setVisible()
should always be invoked on EDT.
请注意,该方法setVisible()
应始终在 EDT 上调用。
回答by Rich
Simplest way I've found that doesn't have inconsistency across platforms:
我发现跨平台没有不一致的最简单方法:
setVisible(false); setVisible(true);
设置可见(假);设置可见(真);
回答by Mr Ed
This simple method worked for me perfectly in Windows 7:
这个简单的方法在 Windows 7 中非常适合我:
private void BringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if(jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
回答by christopher
The rules governing what happens when you .toFront() a JFrame are the same in windows and in linux :
.toFront() JFrame 的规则在 windows 和 linux 中是相同的:
-> if a window of the existing application is currently the focused window, then focus swaps to the requested window -> if not, the window merely flashes in the taskbar
-> 如果现有应用程序的窗口当前是焦点窗口,则焦点切换到请求的窗口 -> 如果不是,则窗口仅在任务栏中闪烁
BUT :
但 :
-> new windows automatically get focus
-> 新窗口自动获得焦点
So let's exploit this ! You want to bring a window to the front, how to do it ? Well :
所以让我们利用它!你想把窗户放在前面,怎么做?好 :
- Create an empty non-purpose window
- Show it
- Wait for it to show up on screen (setVisible does that)
- When shown, request focus for the window you actually want to bring the focus to
- hide the empty window, destroy it
- 创建一个空的非目的窗口
- 展示下
- 等待它出现在屏幕上(setVisible 这样做)
- 显示时,请求您实际想要获得焦点的窗口的焦点
- 隐藏空窗口,销毁它
Or, in java code :
或者,在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);
}
});
回答by christopher
Hj, all methods of yours are not working for me, in Fedora KDE 14. I have a dirty way to do bring a window to front, while we're waiting for Oracle to fix this issue.
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);
}
}
}
//...
}
And, this works perfectly in my Fedora KDE 14 :-)
而且,这在我的 Fedora KDE 14 中完美运行 :-)
回答by Stefan Reich
Here's a method that REALLY works (tested on Windows Vista) :D
这是一种真正有效的方法(在 Windows Vista 上测试过):D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
The fullscreen variable indicates if you want the app to run full screen or windowed.
fullscreen 变量指示您是否希望应用程序全屏或窗口运行。
This does not flash the task bar, but bring the window to front reliably.
这不会使任务栏闪烁,而是可靠地将窗口带到前面。
回答by Jarekczek
I tested your answers and only Stefan Reich's oneworked for me. Although I couldn't manage to restore the window to its previous state (maximized/normal). I found this mutation better:
我测试了您的答案,只有Stefan Reich 的答案对我有用。虽然我无法将窗口恢复到以前的状态(最大化/正常)。我发现这个突变更好:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
That is setState
instead of setExtendedState
.
那是setState
代替setExtendedState
.