PyQt5 端口:如何隐藏 window 并让它出现在同一位置

PyQt5 port: how do I hide a window and let it appear at the same position

我正在将 PyQt4 程序移植到 PyQt5。其中一部分是隐藏 window,截取 window 后面的区域的屏幕截图并再次显示 window,这在 PyQt4 上工作得很好。

使用我的 PyQt5 端口,一切正常,但是 window 出现在程序启动时的位置,而不是调用 hide() 方法之前的位置。

我正在 Linux 盒子上进行测试。相关代码精简为:

import sys
from PyQt5.QtCore import QTimer
from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,
                             QGridLayout, QPushButton)

class demo(QMainWindow):

    def __init__(self):
        super().__init__()

        mainWidget = QWidget(self)
        layout = QGridLayout(mainWidget)
        self.setCentralWidget(mainWidget)

        self.testButton = QPushButton(self)
        self.testButton.setText('Test')
        self.testButton.clicked.connect(self.hideMe)
        layout.addWidget(self.testButton, 0, 0)

    def hideMe(self):
        self.hide()
        QTimer.singleShot(300, self.showMe)

    def showMe(self):
        self.show()
        self.move(self.pos())

app = QApplication(sys.argv)
mainWindow = demo()
mainWindow.show()
sys.exit(app.exec_())

在 showMe() 中,self.pos() 实际上包含正确的坐标,但是 window 并没有移动到那里(但是它在开始后的 "original" 位置).

当我e。 G。相反,执行 self.move(10, 10),window 实际上已移到那里。但是一旦我使用一个变量(我也尝试将 self.pos 的 x 和 y 保存在一个变量中并改为使用它),window 就会显示在它开始后的位置。

为什么使用整数的 move() 调用实际上移动了 window,而使用变量的 move() 调用却没有?如何将 window 移动到隐藏之前的位置?

感谢大家的帮助!

编辑(也许是为了找出不同之处):

使用 PyQt4 的完全相同的代码有效:

import sys

from PyQt4.QtCore import QTimer
from PyQt4.QtGui import (QApplication, QMainWindow, QWidget,
                         QGridLayout, QPushButton)

class demo(QMainWindow):

    def __init__(self):
        super().__init__()

        mainWidget = QWidget(self)
        layout = QGridLayout(mainWidget)
        self.setCentralWidget(mainWidget)

        self.testButton = QPushButton(self)
        self.testButton.setText('Test')
        self.testButton.clicked.connect(self.hideMe)
        layout.addWidget(self.testButton, 0, 0)

    def hideMe(self):
        self.hide()
        QTimer.singleShot(300, self.showMe)

    def showMe(self):
        self.show()
        self.move(self.pos())

app = QApplication(sys.argv)
mainWindow = demo()
mainWindow.show()
sys.exit(app.exec_())

那么为什么在这种情况下 Qt5 的行为与 Qt4 不同?

如果我在 hideMeshowMe 中使用 self.old_pos,那么它适用于我 (Linux)。

def hideMe(self):
    self.old_pos = self.pos()
    self.hide()
    QTimer.singleShot(300, self.showMe)

def showMe(self):
    self.show()
    self.move(self.old_pos)

似乎在 Qt5 中,如果几何形状完全相同,则不会重新设置 - 但我不知道为什么这种行为发生了变化,或者它是否是一个错误。请注意,受影响的不仅仅是位置 - 调整大小也会被忽略。

这是解决该问题的技巧:

from PyQt5.QtCore import QMargins

class demo(QMainWindow):
    ...

    def hideMe(self):
        print('hide:', self.geometry())
        self.hide()
        QTimer.singleShot(300, self.showMe)

    def showMe(self):
        print('show1:', self.geometry())
        hack = QMargins(0, 0, 0, 1)
        self.setGeometry(self.geometry() + hack)
        self.show()
        self.setGeometry(self.geometry() - hack)
        print('show2:', self.geometry())

更新:

经过进一步调查,似乎有一个更简单的解决方案。如果 window 的几何形状在 window 首次显示之前明确设置,则在随后的 hide()/show() 之后它不会移回其原始位置。在这种情况下,不需要其他 hacks/work-arounds。

这确实像是一个错误。

其他解决方法可以设置 QWindow 位置而不是小部件的位置,例如:

windowHandle()->setPosition(windowHandle()->position());

或在show()之前设置WA_Moved属性:

setAttribute(Qt::WA_Moved);

我认为 ekhumoro 的回答是最好的。如果您打算使用变通方法,最好将其明确化,而不是隐式修改。