C++ 如何在 Qt 中为 QMainWindow 切换“始终在顶部”而不会导致闪烁或闪光?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2855968/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-28 11:17:59  来源:igfitidea点击:

How do I toggle 'always on top' for a QMainWindow in Qt without causing a flicker or a flash?

c++qtwindow-managers

提问by Jake Petroules

void MainWindow::on_actionAlways_on_Top_triggered(bool checked)
{
    Qt::WindowFlags flags = this->windowFlags();
    if (checked)
    {
        this->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
        this->show();
    }
    else
    {
        this->setWindowFlags(flags ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
        this->show();
    }
}

The above solution works but because setWindowFlags hides the window, it needs to be re-shown and of course that doesn't look very elegant. So how do I toggle "always on top" for a QMainWindow without that "flashing" side effect?

上述解决方案有效,但由于 setWindowFlags 隐藏了窗口,因此需要重新显示,当然这看起来不是很优雅。那么如何在没有“闪烁”副作用的情况下为 QMainWindow 切换“始终在顶部”?

采纳答案by HostileFork says dont trust SE

Nokia says no:

诺基亚说不

It is not possible to make changes to the window flags once the window has been created without causing flicker. Flicker is unavoidable since the window needs to be recreated.
一旦创建了窗口,就不可能在不引起闪烁的情况下更改窗口标志。闪烁是不可避免的,因为需要重新创建窗口。

But sometimes if you're stuck with a flashing effect that's kind of ugly like this, you can intentionally drag it out to make it seem like something "cool" just happened.

但有时,如果您遇到像这样丑陋的闪烁效果,您可以故意将其拖出,让它看起来像是刚刚发生的“很酷”的事情。

Maybe pop up a little progress bar that's not in the window, say "Adjusting Window Properties!"...fade the window out of existence and then back in, and close the progress bar popup.

也许会弹出一个不在窗口中的小进度条,说“调整窗口属性!”...淡出窗口,然后再回来,然后关闭进度条弹出窗口。

回答by Jake Petroules

Well, for a solution I figured I'd look in the Mono sources, since I know the .NET Form class (System.Windows.Forms) has a TopMost property.

好吧,对于一个解决方案,我想我会查看 Mono 源代码,因为我知道 .NET Form 类(System.Windows.Forms)有一个 TopMost 属性。

The solution I found for my Qt program was:

我为 Qt 程序找到的解决方案是:

void MainWindow::on_actionAlways_on_Top_triggered(bool checked)
{
#ifdef Q_OS_WIN
    // #include <windows.h>
    if (checked)
    {
        SetWindowPos(this->winId(), HWND_TOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
    }
    else
    {
        SetWindowPos(this->winId(), HWND_NOTOPMOST, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
    }
#else
    Qt::WindowFlags flags = this->windowFlags();
    if (checked)
    {
        this->setWindowFlags(flags | Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint);
        this->show();
    }
    else
    {
        this->setWindowFlags(flags ^ (Qt::CustomizeWindowHint | Qt::WindowStaysOnTopHint));
        this->show();
    }
#endif
}

回答by jimmy

Tested with

测试过

  • Qt 5.2.1 on windows XP
  • Qt 5.2 on OS X 10.9
  • Windows XP 上的 Qt 5.2.1
  • OS X 10.9 上的 Qt 5.2
    void ConsoleUI::onAllwaysTop(bool checked)
    {
        Qt::WindowFlags flags = windowFlags();
        if (checked)
        {
            flags ^= Qt::WindowStaysOnBottomHint;
            flags |= Qt::WindowStaysOnTopHint;
        }
        else
        {
            flags ^= Qt::WindowStaysOnTopHint;
            flags |= Qt::WindowStaysOnBottomHint;
        }
        setWindowFlags(flags);
        show();
    }