【问题标题】:PyQt5 port: how do I hide a window and let it appear at the same positionPyQt5端口:如何隐藏一个窗口并让它出现在同一位置
【发布时间】:2017-02-25 17:50:57
【问题描述】:

我正在将 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() 实际上包含正确的坐标,但窗口并没有移动到那里(而是移动到它在启动后的“原始”位置)。

当我 e. 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 不同?

【问题讨论】:

  • hideMeshowMe 中打印self.pos() 并查看差异。
  • 重点是:这里没有区别!
  • @TobiasLeupold。如果您说明您使用的是哪个 linux 发行版以及哪个窗口管理器,将会很有帮助。

标签: python pyqt4 porting pyqt5


【解决方案1】:

如果我在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)

【讨论】:

  • 我之前试过这个,但这里没有任何改变。另外,我很高兴知道为什么 Qt4 版本有效(请参阅我对原始帖子的编辑),而 Qt5 版本无效(仅因导入语句不同)。
【解决方案2】:

似乎在 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())

更新

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

【讨论】:

  • 这实际上可以解决问题。但这对我来说确实是一个错误!如果它不是功能,我会对此进行调查并提交错误;-) 谢谢!
  • 这也可以用“真正的”C++ Qt 程序生成,所以我认为这确实是一个错误。我在bugreports.qt.io/browse/QTBUG-56579 上发布了一份关于此的报告
  • @TobiasLeupold。我找到了一个对我有用的更简单的解决方案 - 请参阅我的更新答案。
  • 感谢您的进一步调查。我也会更新 Qt 错误。
【解决方案3】:

这确实看起来像一个错误。

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

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

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

setAttribute(Qt::WA_Moved);

我认为 ekhumoro 的回答是最好的。如果您要使用解决方法,最好将其明确化,而不是隐式破解。

【讨论】:

  • 这没有争议。问题是之后移动窗口。 OP 能够在 qt4 中执行 show(); move(pos()),但这在 qt5 中不起作用。
  • 感谢您的解释,我已经修复了答案。
猜你喜欢
  • 2020-07-01
  • 2011-02-12
  • 2014-02-25
  • 2011-05-19
  • 1970-01-01
  • 2011-09-17
  • 2018-07-03
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多