Python PyQt5端口:如何隐藏窗口并使其显示在同一位置

Python PyQt5端口:如何隐藏窗口并使其显示在同一位置,python,pyqt4,porting,pyqt5,Python,Pyqt4,Porting,Pyqt5,我正在将PyQt4程序移植到PyQt5。其中一部分是隐藏窗口,截取窗口后面区域的屏幕快照,然后再次显示窗口,这在PyQt4中运行良好 使用PyQt5端口,一切正常,但窗口显示在程序启动时的位置,而不是调用hide()方法之前的位置 我正在Linux机器上测试这个。相关代码可细分为: import sys from PyQt5.QtCore import QTimer from PyQt5.QtWidgets import (QApplication, QMainWindow, QWidget,

我正在将PyQt4程序移植到PyQt5。其中一部分是隐藏窗口,截取窗口后面区域的屏幕快照,然后再次显示窗口,这在PyQt4中运行良好

使用PyQt5端口,一切正常,但窗口显示在程序启动时的位置,而不是调用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()实际上包含正确的坐标,但窗口没有移动到那里(而是移动到启动后的“原始”位置)

当我。G做一个self.move(10,10)相反,窗口实际上被移动到了那里。但只要我使用了一个变量(我还试图将self.pos的x和y保存在一个变量中并使用它),窗口就会显示在启动后的位置

为什么使用整数的move()调用实际上会移动窗口,而使用变量的move()调用则不会移动窗口?如何将窗口移动到隐藏前的位置

谢谢你的帮助

编辑(也许是为了找出区别):

使用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不同呢?

如果我在
hideMe
showMe
中使用
self.old\u pos
,那么它对我有效(Linux)


似乎在Qt5中,如果几何体完全相同,就不会重新设置,但我不知道为什么会改变这种行为,或者这是否是一个bug。请注意,受影响的不仅仅是位置,还忽略了调整大小

下面是一个解决此问题的方法:

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())
更新


经过进一步调查,似乎有一个更简单的解决方案。如果在首次显示窗口之前显式设置了窗口的几何图形,则在后续的hide()/show()之后,它将不会移回其原始位置。在这种情况下,不需要其他黑客/变通方法。

这看起来确实像一个bug

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

windowHandle()->setPosition(windowHandle()->position());
或者在
show()之前设置WA_Moved属性


我认为Ekhumaro的答案是最好的。如果要使用解决方案,最好将其显式化,而不是隐式黑客。

hideMe
showMe
中打印
self.pos()@托比亚斯鲁波尔德。如果您说明您使用的是哪个linux发行版,以及哪个窗口管理器,这会很有帮助。我以前尝试过这个,但在这里没有任何改变。另外,如果我能找出为什么Qt4版本可以工作(请参阅我对原始帖子的编辑),而Qt5版本不能工作(这只与import语句不同),那将是一件好事。这确实起到了作用。但对我来说,它确实像一只虫子!我将对此进行调查,如果它不是功能,则提交一个bug;-)谢谢这也可以用一个“真实”的C++ QT程序来制作,所以我认为这是一个bug。我在@TobiasLeupold上发布了一份关于这方面的报告。我发现了一个更简单的解决方案,适合我-请参阅我的更新答案。感谢您的进一步调查。我也会更新Qt错误。这没有争议。问题是以后移动车窗。OP能够做
show();在qt4中移动(pos())
,但在qt5中不起作用。感谢您的解释,我已经修复了答案。
windowHandle()->setPosition(windowHandle()->position());
setAttribute(Qt::WA_Moved);