是否有一种跨平台的方式来进行 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_())
我最近尝试使用全屏导致在 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_())