当远程控制机制激活应用程序中的某些内容时,我们需要将Java应用程序带到前台.
为了得到这个,我们在类的被调用方法中实现了代表我们的应用程序的框架(a的扩展JFrame
)在实现之后:
setVisible(true); toFront();
在Windows XP下,这在第一次调用时工作,第二次只有任务栏中的选项卡闪烁,框架不再出现在前面.Win2k也是如此.在Vista上似乎工作正常.
你有什么想法?
可能的解决方案是:
java.awt.EventQueue.invokeLater(new Runnable() { @Override public void run() { myFrame.toFront(); myFrame.repaint(); } });
我JFrame
在Ubuntu(Java 1.6.0_10)下带来了同样的问题.我能解决它的唯一方法是提供一个WindowListener
.具体来说,我必须设置我JFrame
始终保持在顶部toFront()
调用,并提供windowDeactivated
事件处理程序setAlwaysOnTop(false)
.
因此,这里是可以放入基础的代码,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上调用该方法.
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中完美运行:-)