[英]How to bring a window to the front?
当远程控制机制激活应用程序中的某些内容时,我们需要将Java应用程序带到前台。
为了得到这个,我们在类的被调用方法中实现了代表我们的应用程序的框架( JFrame
扩展)在实现之后:
setVisible(true);
toFront();
在Windows XP下,这在第一次调用时工作,第二次只有任务栏中的选项卡闪烁,框架不再出现在前面。 Win2k也是如此。 在Vista上似乎工作正常。
你有什么想法?
可能的解决方案是:
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
myFrame.toFront();
myFrame.repaint();
}
});
在Ubuntu(Java 1.6.0_10)下将JFrame
引入前端时遇到了同样的问题。 我能解决它的唯一方法是提供一个WindowListener
。 具体来说,每当调用toFront()
时,我必须将我的JFrame
设置为始终保持在顶部,并为setAlwaysOnTop(false)
提供windowDeactivated
事件处理程序。
因此,这里是可以放入基础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,似乎没有必要使用WindowListener
来调用super.setAlwaysOnTop(false)
- 可以观察到; 此代码已移至方法toFront()
和setVisible()
。
请注意,应始终在EDT上调用方法setVisible()
。
Windows具有防止窗口窃取焦点的功能; 相反,它会闪烁任务栏图标。 在XP中它默认是打开的(我看到改变它的唯一地方是使用TweakUI,但在某处有一个注册表设置)。 在Vista中,他们可能已经更改了默认值和/或将其作为用户可访问的设置暴露在开箱即用的UI中。
从Windows 2K开始,防止窗户强迫自己到前方并获得焦点是一个特征(而且我,我很感激它)。
也就是说,我有一个小的Java应用程序,用来提醒我在工作时记录我的活动,它每30分钟就会成为活动窗口(当然可以配置)。 它始终在Windows XP下始终如一,并且永远不会闪烁标题栏窗口。 它使用以下代码,作为计时器事件触发的结果在UI线程中调用:
if(getState()!=Frame.NORMAL) { setState(Frame.NORMAL); }
toFront();
repaint();
(如果最小化,第一行恢复......实际上如果最大化也会恢复它,但我从来没有这样做)。
虽然我通常将这个应用程序最小化,但通常它只是在我的文本编辑器后面。 并且,就像我说的,它总是有效的。
我确实知道你的问题可能是什么 - 也许你有一个setVisible()调用的竞争条件。 除非在调用窗口时实际显示窗口,否则toFront()可能无效; 我之前遇到过requestFocus()这个问题。 您可能需要在窗口激活事件的UI侦听器中放置toFront()调用。
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开始,这段代码似乎运行正常。
这是一种真正有效的方法(在Windows Vista上测试):D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
全屏变量指示您是希望应用程序全屏运行还是窗口运行。
这不会闪烁任务栏,但可以将窗口可靠地拉到前面。
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中完美运行:-)
这个简单的方法在Windows 7中完美适用于我:
private void BringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if(jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
我测试了你的答案,只有Stefan Reich的一个为我工作。 虽然我无法将窗口恢复到以前的状态(最大化/正常)。 我发现这个突变更好:
view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
这是setState
而不是setExtendedState
。
最简单的方法我发现跨平台没有不一致性:
调用setVisible(假); 调用setVisible(真);
管理.toFront()JFrame时发生的事情的规则在windows和linux中是相同的:
- >如果现有应用程序的窗口当前是焦点窗口,则焦点交换到请求的窗口 - >如果没有,窗口只会在任务栏中闪烁
但是:
- >新窗口自动获得焦点
所以让我们利用这个! 你想给前面带一个窗口,怎么做? 好 :
或者,在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);
}
});
为了避免窗口在被隐藏后返回可见时失去焦点所需要的是:
setExtendedState(JFrame.NORMAL);
像这样:
defaultItem.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
showWindow();
setExtendedState(JFrame.NORMAL);
}
});
对于toFront()方法,javadoc中有许多警告可能会导致您的问题。
但无论如何,当“只有任务栏中的选项卡闪烁”时,我会猜测应用程序是否已最小化? 如果是这样,javadoc的以下行可能适用:
“如果此窗口可见,则将此窗口置于前面,并使其成为焦点窗口。”
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.