是否有一种跨平台的方式来进行 PySide 自发调整大小事件检查?

Is there a cross-platform way to do PySide spontaneous resize event checking?

我最近尝试使用全屏导致在 Mac OS X 和 Linux 下出现不同的行为。

我让我的代码查询屏幕尺寸然后最大化。那是我唯一一次想要调整大小。一切最大化后,我绘制并重新定位项目。

在 Linux 上,检查调整大小事件是否是自发的。

在 Mac OS X 上,我在 init 中将一个变量 (self.unsized) 初始化为 True 然后在调整大小事件中,我检查 self.unsized 是否为真。如果是,我会进行所有重新定位等操作,然后将 self.unsized 设置为 False。

我原以为 Mac OS X 版本可以在 Linux 上运行,但显然,调整大小事件需要在 Linux 上更频繁地触发,并且因此,第一次通过事件将 self.unsized 设置为 False 发生得太早,因为需要第二次调整大小才能全屏显示。

有跨平台的方法吗?还是我只需要在执行任何操作之前查询我的 OS?

代码

#!/usr/bin/env python3
# -*- coding: utf-8 -*-

import sys

from PySide.QtCore import *
from PySide.QtGui  import *


class MyView(QGraphicsView):

    def __init__(self, parent=None):
        super(MyView, self).__init__(parent)
        self.parent = parent

        self.scene = QGraphicsScene(self)
        self.setScene(self.scene)

class UI(QDialog):

    def __init__(self, parent=None):
        super(UI, self).__init__(parent)
        self.parent = parent

        self.unsized = True

        self.view = MyView(self)
        gridLayout = QGridLayout()
        gridLayout.addWidget(self.view, 0, 0, 1, 1)
        self.setLayout(gridLayout)

        self.setWindowFlags(Qt.FramelessWindowHint)
        self.showFullScreen()

    def resizeEvent(self, event):
        super(UI, self).resizeEvent(event)
        print("DEBUG: platform = {0}, spontaneous = {1}, unsized = {2}"
              .format(sys.platform, event.spontaneous(), self.unsized))

        if ((sys.platform.startswith("linux")  and event.spontaneous()) or
            (sys.platform.startswith("darwin") and self.unsized)):
            self.view.setFrameShape(QFrame.NoFrame)

            bounds = self.geometry()
            self.X1, self.Y1, self.w,  self.h  = bounds.getRect()

            self.view.setFrameShape(QFrame.NoFrame)
            self.view.scene.setSceneRect(0, 0, self.w - 42, self.h - 42)
            self.view.setFixedSize(self.w - 40, self.h - 40)

            self.unsized = False

app = QApplication(sys.argv)
ui = UI()
ui.show()
sys.exit(app.exec_())

正如评论中所指出的,Qt 文档主题 Window Geometry - X11 Peculiarities explains why things work differently on Linux - and the docs for showFulScreen 指出了一些进一步的困难。

总结:Qt 必须等待某些异步 X11 事件发生,然后才能尝试模拟 Linux 上缺少的 maximize/full-screen 功能。

这表明一个可能的解决方法是使用单次计时器而不是等待第一个 resizeEvent。这不是一个精确的解决方案,因为无法知道确切在应用您自己的设置之前需要等待多长时间。但是,在我的 Linux 系统上,第一个调整大小事件发生在大约 1 毫秒后,第二个调整事件发生在大约 5-20 毫秒后。所以 50 毫秒的延迟似乎是绝对安全的(或者如果你真的很偏执,就把它稍微长一点):

class UI(QDialog):
    def __init__(self, parent=None):
        super(UI, self).__init__(parent)
        self.view = MyView(self)
        gridLayout = QGridLayout()
        gridLayout.addWidget(self.view, 0, 0, 1, 1)
        self.setLayout(gridLayout)    
        self.setWindowFlags(Qt.FramelessWindowHint)
        self.showFullScreen()
        QTimer.singleShot(50, self.doResize)

    def doResize(self):
        self.view.setFrameShape(QFrame.NoFrame)
        bounds = self.geometry()
        self.X1, self.Y1, self.w,  self.h  = bounds.getRect()
        self.view.setFrameShape(QFrame.NoFrame)
        self.view.scene.setSceneRect(0, 0, self.w - 42, self.h - 42)
        self.view.setFixedSize(self.w - 40, self.h - 40)

app = QApplication(sys.argv)
ui = UI()
sys.exit(app.exec_())

另一种可能的解决方法是确保两个调整大小事件 总是 发生,无论平台是什么。我只在 Linux 上测试过这个,但也许像这样的东西会起作用:

class UI(QDialog):   
    def __init__(self, parent=None):
        super(UI, self).__init__(parent)
        self.unsized = True    
        self.view = MyView(self)
        gridLayout = QGridLayout()
        gridLayout.addWidget(self.view, 0, 0, 1, 1)
        self.setLayout(gridLayout)
        self.setWindowFlags(Qt.FramelessWindowHint)

    def resizeEvent(self, event):
        super(UI, self).resizeEvent(event)
        if not self.isFullScreen():
            self.showFullScreen()
        elif self.unsized:
            self.unsized = False
            self.view.setFrameShape(QFrame.NoFrame)       
            bounds = self.geometry()
            self.X1, self.Y1, self.w,  self.h  = bounds.getRect()
            self.view.setFrameShape(QFrame.NoFrame)
            self.view.scene.setSceneRect(0, 0, self.w - 42, self.h - 42)
            self.view.setFixedSize(self.w - 40, self.h - 40)

app = QApplication(sys.argv)
ui = UI()
ui.show()
sys.exit(app.exec_())