My latest attempt to use the full screen results in different behaviors under Mac OS X and Linux.
I have my code query the screen size and then maximize. That's the only time I want to resize. Once everything is maximized, I draw and reposition items.
On Linux, a check to see if the resize event is spontaneous does the trick.
On Mac OS X, I initialize a variable (self.unsized) to True in the init and then in the resize event, I check to see if self.unsized is True. If it is, I do all my repositioning, etc, and set self.unsized to False.
I would have expected the Mac OS X version to work on Linux, but apparently, the resize event needs to fire more often on Linux, and so, the first time through the event, setting self.unsized to False happens too early, as there needs to be a second resize to get to full screen.
Is there a cross-platform approach? Or do I just need to query my OS before I do anything?
The code
#!/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_())
As pointed out in the comments, the Qt docs topic Window Geometry - X11 Peculiarities explains why things work differently on Linux - and the docs for showFulScreen point out some further difficulties.
In summary: Qt has to wait for certain asynchronous X11 events to happen before it can attempt to emulate the maximize/full-screen capabilities which are missing on Linux.
This suggests one possible work-around would be to use a single-shot timer instead of waiting for the first resizeEvent
. This is not an precise solution, because there is no way to know exactly how long to wait before applying your own settings. However, on my Linux system the first resize event occurs after about 1 ms and the second one after about 5-20 ms. So a 50 ms delay would seem perfectly safe (or just make it slightly longer if you're really paranoid):
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_())
Another possible work-around would be to ensure that two resize events always occur, no matter what the plaform. I have only tested this on Linux, but perhaps something like this would work:
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_())