QMainWindow:showMaximized 仅在第一次调用时有效

QMainWindow:showMaximized only works the first time it is called

我有一个函数 button_max_slot 使用 showMaximized 最大化 window,另一个函数 button_restore_slot 恢复 window 的大小和地方。我第一次调用 button_max_slot 时效果很好,然后我使用 button_restore_function 来恢复 window 的大小和位置。但是我第二次调用 button_max_slot 来最大化 window,它没有用。我调用 self.isMaximized() 并且它 returns 是真的,但实际上 window 不 maximized.What 我应该如何解决这个问题?这是一个最小的可重现示例:

from PyQt5 import  QtWidgets
import sys

class MyWindow(QtWidgets.QMainWindow):
    last_geometry = None
    def __init__(self):
        super().__init__()
        self.resize(960, 540)

        self.ButtonMax = QtWidgets.QPushButton(self)
        self.ButtonMax.setObjectName("ButtonMax")
        self.ButtonMax.setText("Max")
        self.ButtonMax.move(100, 100)

        self.ButtonRestore = QtWidgets.QPushButton(self)
        self.ButtonRestore.setText("Restore")
        self.ButtonRestore.setObjectName("ButtonRestore")
        self.ButtonRestore.move(300, 100)
        self.ButtonRestore.setEnabled(False)

        self.ButtonMax.clicked.connect(self.button_max_slot)
        self.ButtonRestore.clicked.connect(self.button_restore_slot)

    def button_max_slot(self):
        self.last_geometry = self.geometry()
        self.showMaximized()
        self.ButtonRestore.setEnabled(True)
        self.ButtonMax.setEnabled(False)

    def button_restore_slot(self):
        self.setGeometry(self.last_geometry)
        self.ButtonRestore.setEnabled(False)
        self.ButtonMax.setEnabled(True)

if __name__ == "__main__":
    app = QtWidgets.QApplication(sys.argv)
    myshow = MyWindow()
    myshow.show()
    sys.exit(app.exec_())

tl;博士

使用 showNormal() 而不是 setGeometry() 来恢复 window 状态。

说明

虽然不直观,但仍然可以设置 window 的几何形状,即使它的状态 应该 允许它,那是因为设置 window 的状态与设置其几何形状 不同

简单地说,设置window状态告诉底层platform/window管理器根据指定状态“选择”window的几何结构,而设置几何结构要求系统显式设置 window 的位置和大小。系统是否允许,另当别论。

需要考虑的一件重要事情是 QWidget(即使是顶级的,包括 QDialog 或 QMainWindow)不是显示在屏幕上的实际 window屏幕。您看到的是 QWindow(该小部件的系统 window 的抽象表示),它实际上 包含 QWidget(或其任何继承的类)。设置状态作用于 QWindow,而设置几何通常作用于包含的小部件,不包括可能的 window 框架。

例如,我能够在我的 Linux 系统上重现您的问题,但是 ekhumoro cannot,即使我们都使用 Linux(我们都使用 相似 window 经理,但他们仍然不同:他在 OpenBox,我在 FluxBox)。此外,即使使用系统功能,我在按下“最大”按钮后也会出现不一致的行为。

事实上 you got 最大化的 window 状态,即使它不像 看起来 那样,与此完全相关:state 最大化,几何不是(因为你改变了它)。

反过来考虑:您可以手动调整 window 的大小,以便 精确地 占据整个可用屏幕大小,但这并不能做到maximized:您可能仍然可以在其标题栏中看到“最大化”按钮(不是“标准化”按钮),甚至可能看到通常隐藏的 window 边框window 实际上 已最大化。

请注意,在不同的 OS 或 window 管理器上显示的不一致行为依赖于两个方面:OS/wm 实现和 Qt 尝试在所有系统中使用“标准化”行为.

解决方案很简单:只需使用 showNormal() 而不是 setGeometry() 来恢复状态。

它通常适用于所有系统,但 linux 上一些非常具体的 window 管理器除外(可能在最近的 Windows/MacOS 版本中有一些“非标准”行为),但这是接受的方法。

对于这些情况,您可以考虑通过覆盖该事件的顶层 window 的 changeEvent(), checking if the event.type() is a WindowStateChange and eventually decide the behavior based on the current windowState() and the oldState() 来存储和恢复 几何。
请记住,window 状态是 标志 ,因此它们可以是 Qt.WindowState 枚举的 OR 组合。