我们有一个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
设置为始终保持在最上层,并提供windowDeactivated
事件处理程序,以便调用setAlwaysOnTop(false)
。
因此,以下是可以放置在基本JFrame
中的代码,该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()
方法中。
请注意,setVisible()
方法应始终在EDT上调用。
.setAlwaysOnTop(true);
是唯一有效的选项。 - DGolbergsetAlwaysOnTop(true)
是我在 Windows 10 下运行它的唯一方法 - 谢谢! - Hartmut PfarrWindows有防止窗口抢占焦点的功能;相反,它会闪烁任务栏图标。在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版本,该代码似乎能够正常工作。
super.setAlwaysOnTop(false);
的作用是让窗口不总是置顶,这是为了消除我们之前设置的 true
以将窗口置于前台,对吗?我问这个问题是因为在您的代码中,窗口在我的情况下仍然总是置顶,显然我不想要这样。在 Windows 10 上运行 jre1.8.0_66。 - Bram Vanroy这里有一个真正有效的方法(在Windows Vista上测试通过):D
frame.setExtendedState(JFrame.ICONIFIED);
frame.setExtendedState(fullscreen ? JFrame.MAXIMIZED_BOTH : JFrame.NORMAL);
全屏变量表示您是否希望应用程序以全屏或窗口模式运行。view.setState(java.awt.Frame.ICONIFIED);
view.setState(java.awt.Frame.NORMAL);
setState
而不是 setExtendedState
。你好,我在 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中,这个功能完美运作 :-)
private void BringToFront() {
java.awt.EventQueue.invokeLater(new Runnable() {
@Override
public void run() {
if(jFrame != null) {
jFrame.toFront();
jFrame.repaint();
}
}
});
}
repaint()
不是必需的,invokeLater()
已经完成了。谢谢。 - Matthieu我发现最简单的方法是没有跨平台不一致性的:
setVisible(false); setVisible(true);
// 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);
}
});
invokeLater
调用toFront()
方法。下面包含了一个简单的答案,但它不是被接受的答案。不过,这个简单的答案确实有效。完美无缺。 - Erick Robertson