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 不同?
如果我在 hideMe
和 showMe
中使用 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 的回答是最好的。如果您打算使用变通方法,最好将其明确化,而不是隐式修改。
我正在将 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 不同?
如果我在 hideMe
和 showMe
中使用 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 的回答是最好的。如果您打算使用变通方法,最好将其明确化,而不是隐式修改。