将窗口置于前台 -> raise()、show()、activateWindow() 都无效

33

在我的Qt应用程序中,我会在默认浏览器中打开一个URL。之后,我想再次将应用程序的主窗口置于前台。

我尝试了所有可以找到的方法,但都不起作用。它只是在Windows 7任务栏中闪烁。 下面是一个示例:

this->viewer->show();
this->viewer->raise();
this->viewer->activateWindow();

*viewer 是指向 QmlApplicationViewer 的指针,QmlApplicationViewer 派生自 QDeclarativeView。


你为什么想从用户的控件中窃取焦点? - Adrian McCarthy
1
因为它会被我的应用程序自动打开的浏览器窃取。我只想在他允许我的 Twitter 应用程序访问后再次将我的窗口弹出。 - Hedge
1
由于Z顺序的存在,一旦用户关闭浏览器窗口,您的应用程序将自动重新启动。它是在新打开的浏览器窗口下面的Z顺序中的下一个窗口。您无需做任何事情。 - Cody Gray
1
@Code Gray:是的,那是正确的,但我宁愿把它放在前面。浏览器也会在前面打开,所以有什么区别呢? - Hedge
2
所以每个人都抱怨,但没有人想给出答案?我也有同样的问题。当用户按下设置时,会打开一个新窗口,但如果他们没有注意到并再次按下设置,则设置窗口将留在后面,我想说“嘿,我在这里,在这里,我为你弹回前面”。一种解决方案是使setVisibile(false),然后setVisible(true),但我不喜欢这个解决方案,它应该只是弹出到前面,而不需要关闭和重新打开它。 - Lilian A. Moraru
显示剩余5条评论
7个回答

41

试试这个:

viewer.setWindowState( (windowState() & ~Qt::WindowMinimized) | Qt::WindowActive);
viewer.raise();  // for MacOS
viewer.activateWindow(); // for Windows

这对我的项目有效(在我项目的查看器中是QMainWindow):https://github.com/iptton/Rythem


1
QWindow::setWindowState文档中指出,枚举值Qt::WindowActive不是一个被接受的参数。 - ManuelSchneid3r
根据源代码,当参数等于Qt::WindowActive时,setWindowState会直接返回。而raise()活动窗口()适用于这种情况。但如果窗口的状态不是最小化的,状态也不等于Qt::WindowActive,那么代码就会起作用。 - iptton
1
这个方法在Win10上对我有效。我所需的只是setWindowState(与show()组合以从托盘还原应用程序)。谢谢! - smoothware
@RuiBotelho 如果你最小化了窗口,那么你的方法就无法将窗口置于前台。 - iMath

12

1
谢谢你的解释。你的方法相当巧妙。但是,作为一个坚定的便携式软件支持者,我不想去调整别人电脑的注册表。 是否有另一种方法,比如将窗口置顶? - Hedge
17
这并不是仅限于Windows的“问题”,而是针对所有令人厌烦且窃取注意力的应用程序的一种“解决方案”。Windows发出信号表示应用程序需要用户的注意,但最终用户仍然有掌控权。 - Adrian McCarthy
7
无论你戴什么颜色的帽子都没关系:那只是将其“修复”在你的本地计算机上,而不是客户端的计算机。由于UAC的存在,也就是Windows的较新版本中引入的用户账户控制功能,我的注册表设置对你的恶意应用程序是安全的! - Cody Gray
1
activateWindow() 在我的Win'7上,使用4.8.6非常好 :) - mlvljr
我在 MacOS 上遇到了同样的问题。 - c z
很棒的回答,不幸的是这不是好消息 :)) - Alex Seceleanu

10
我是这样做的:
{
 this->show(); // Restore from systray
 this->setWindowState(Qt::WindowState::WindowActive); // Bring window to foreground
}

假设 "this" 是你的 QMainWindow。 运作得很棒。


3
for ( QWindow* appWindow : qApplication.allWindows() )
{
  appWindow->show(); //bring window to top on OSX
  appWindow->raise(); //bring window from minimized state on OSX

  appWindow->requestActivate(); //bring window to front/unminimize on windows
}

请注意,在OSX和Windows上,这也会从其他虚拟桌面中打开窗口。我没有在Linux上测试过,但可能有效。

非常感谢。这是在我所有情况下都能正常工作的唯一方法。 - pier_nasos

2

这个问题不仅限于Windows操作系统...在Linux上我也遇到了同样的问题。我的解决方法是在重新打开窗口之前先关闭(close())它。


0

对于Windows,我是使用WinAPI来完成的。此外,您需要知道窗口标题;

#include <windows.h>
const QString windowTitle = "Some title";

HWND hwnd = ::FindWindowA(NULL, windowTitle.toLocal8Bit());
if (hwnd != NULL) {
    if (::IsWindowVisible(hwnd)) {
        ::SwitchToThisWindow(hwnd, TRUE);
    }
}
 

有趣的行为 - 尝试将应用程序置于前面 - 它固执地留在后面,但任务栏上的图标会闪烁以引起注意。 - Thalia

0
以下内容来自论坛,并且对我有效:
auto eFlags = viewer.windowFlags();
viewer.setWindowFlags(eFlags|Qt::WindowStaysOnTopHint);
viewer.show();
viewer.setWindowFlags(eFlags);
viewer.show();

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接