Reputation: 13
I have a function button_max_slot
that use showMaximized
to maximize the window, and another function button_restore_slot
to restore the window's size and place. the first time I call the button_max_slot
it works great, then I use button_restore_function
to restore window's size and place. But the second time I call the button_max_slot
to maximize the window, it didn't work. I call self.isMaximized()
and it returns true, but actually the window doesn't maximized.What should I do to fix this problem?Here is a minimal reproducible example:
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_())
Upvotes: 1
Views: 1058
Reputation: 48479
Use showNormal()
instead of setGeometry()
to restore the window state.
While not intuitive, it's still possible to set a geometry of a window even if its state should not allow it, and that's because setting the state of a window is not the same as setting its geometry.
Simply put, setting the window state tells the underlying platform/window manager to "choose" the geometry of the window based on the specified state, while setting the geometry asks the system to explicitly set the position and size of the window. Whether the system allows it, is another story.
An important thing to consider is that a QWidget (even a top level one, including a QDialog or a QMainWindow) is not the actual window shown on the screen. What you see is the QWindow (an abstract representation of the system's window for that widget), which is what actually contains the QWidget (or any of its inherited classes). Setting the state acts on the QWindow, while setting the geometry normally acts on the contained widget, excluding the possible window frame.
For instance, I'm able to reproduce your issue on my Linux system, but ekhumoro cannot, even though we both are using Linux (we're both using similar window managers, but they're still different: he's on OpenBox, I'm on FluxBox). Furthermore, I get inconsistent behavior after pressing the "Max" button, even if using the system features.
The fact that you got a maximized window state even if it doesn't look like it is, is exactly related to that: the state is maximized, the geometry isn't (because you changed it).
Consider it the other way around: you can manually resize a window in order to precisely occupy the whole available screen size, but that doesn't make it maximized: you can still probably see the "maximize" button in it's title bar (not the "normalize" one), and maybe even the window borders that are normally hidden when the window is actually maximized.
Note that the inconsistent behavior shown on different OS or window managers relies on two sides: the OS/wm implementation and Qt attempts to use a "standardized" behavior across all systems.
The solution is simple: just restore the state using showNormal()
instead of setGeometry()
.
It usually works on all systems, with the exception of some very specific window managers on linux (and maybe some "non standard" behavior in recent Windows/MacOS versions), but it's the accepted approach.
For those cases, you might consider storing and restoring the geometry by overriding the top level window's changeEvent()
, checking if the event.type()
is a WindowStateChange
and eventually decide the behavior based on the current windowState()
and the oldState()
of that event.
Remember that window states are flags, so they can be an OR
combination of Qt.WindowState
enums.
Upvotes: 1