当主窗口保持在顶部时,子窗口被遮挡 - MacOS

8
通常情况下,工具窗口始终位于主窗口顶部,即使失去焦点也是如此。然而,在MacOS上,当主窗口设置窗口标志Qt::WindowStaysOnTopHint时,工具窗口位于其下方。在Windows系统上,工具窗口如预期一样位于主窗口顶部。是否有一种方法可以使主窗口保持在顶部,而工具窗口在其上方?

enter image description here

我的当前Qt版本是5.9.6和5.12.1。 MacOS版本为10.13.4。

这是我的测试代码

#include <QtGui>
#include <QtWidgets>

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    QDialog* mw = new QDialog(0, Qt::WindowStaysOnTopHint | Qt::X11BypassWindowManagerHint);
    mw->setWindowTitle(QLatin1String("Main"));
    mw->resize(400, 300);
    mw->move(100, 100);

    QWidget* d = new QWidget(mw, Qt::Tool);
    d->setWindowTitle(QLatin1String("Tool"));
    d->resize(200, 100);
    d->show();
    mw->exec();
    return app.exec();
}
2个回答

3

抱歉,我没有MacOS系统,但是我可以在Ubuntu下重现并修复您的问题。希望在MacOS下也能起作用。

首先,bnaecker是正确的,你应该调用show()而不是exec()来显示主窗口。如果它是一个QMainWidget而不是QDialog会更好,但这不是问题的原因。

根据文档:

Qt :: Tool:表示小部件是工具窗口。工具窗口通常是一个小窗口,带有比通常更小的标题栏和装饰,通常用于工具按钮的集合。如果有父级,则工具窗口将始终保持在其上方。如果没有父级,则还可以考虑使用Qt :: WindowStaysOnTopHint。如果窗口系统支持,工具窗口可以用稍微轻一些的边框进行装饰。它也可以与Qt :: FramelessWindowHint结合使用。

您的工具小部件有一个父级,所以应该能够正常工作。然而,通过测试,我发现工具窗口应该在工具本身显示时显示,才能像预期的那样保持在顶部...这很奇怪,但这就是我观察到的。

此外,我注意到Qt :: X11BypassWindowManagerHint会搞砸事情...

最后,通过结合这些观察和bnaecker的回复,代码如下:

#include <QtGui>
#include <QApplication>

int main(int argc, char * argv[])
{
    QApplication app(argc, argv);

    // don't set Qt::X11BypassWindowManagerHint if you want the tool to stay on top!
    QDialog* mw = new QDialog(0, Qt::WindowStaysOnTopHint);// | Qt::X11BypassWindowManagerHint);
    mw->setWindowTitle(QLatin1String("Main"));
    mw->resize(400, 300);
    mw->move(100, 100);

    // show main window before tool is shown
    mw->show();

    QWidget* d = new QWidget(mw, Qt::Tool);
    d->setWindowTitle(QLatin1String("Tool"));
    d->resize(200, 100);
    d->show();

    return app.exec();
}

现在,“工具”窗口位于“主”对话框的顶部,并且没有办法使其被其父级隐藏。
请注意,无论您是否为“主”窗口指定了Qt::WindowStaysOnTopHint标志,此方法都可以正常工作。该标志对“工具”保持在“主”窗口顶部的事实没有影响。这使得“主”(因此也是“工具”)位于任何其他应用程序窗口的顶部。

似乎无法正常工作。当主窗口获得焦点时,工具窗口被覆盖。我的当前Qt版本为5.9.6和5.12.1。MacOS版本为10.13.4。 - Degang Guo

2
问题在于你调用了QDialog::exec,而不是直接关于窗口提示。对话框的exec方法将其显示为模态对话框,这意味着在用户关闭对话框之前,不允许与应用程序中的任何其他窗口进行交互。将mw->exec()更改为mw->show()将演示工具窗口确实可以置于主窗口的顶部,而不管窗口提示是什么。
您可能考虑使用一个不是QDialog的主窗口(这是一种不常见的情况)。对话框旨在阻止用户继续使用应用程序,直到回答问题或确认某些内容(例如错误)。它们通常不被认为是用户与应用程序交互的主要窗口。使用另一个QWidget子类,例如QMainWindow,甚至只是带有设置Qt::Window标志的普通QWidget,可能更合适。

然而,当单击主窗口时,工具窗口仍将被覆盖。 - Degang Guo
非常抱歉我的表述不够清楚。通常,工具窗口始终位于主窗口的顶部,即使失去焦点也是如此。然而,当在主窗口中设置了Qt::WindowStaysOnTopHint标志时,工具窗口不再始终位于主窗口的顶部。 - Degang Guo
@郭德纲 是的,没错。我不确定我理解你的观点。那个提示的目标就是要做到这一点,让窗口始终位于其他所有窗口之上。如果这不是你想要的,你需要移除这个标志。 - bnaecker
我希望主窗口保持在其他窗口之上,而工具窗口则保持在主窗口之上。在 MacOS 上能否实现这一点? - Degang Guo
我不相信这是可能的。你可以重写主窗口的事件处理程序,例如focusInEvent,以便它们总是在工具窗口上调用raise()。但我认为这将会很复杂,并且只会使工具窗口通常处于顶部,而不是总是处于顶部。我必须问一下,你为什么想要这种行为?你想做什么? - bnaecker
@myxingkong:“我希望主窗口保持在其他窗口之上,而工具窗口则保持在主窗口之上。”这就是我在我的答案中发布的代码观察到的情况。 - jpo38

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