user2315
user2315

Reputation: 831

PyQT Window: I want to remember the location it was closed at

I have a QDialog, and when the user closes the QDialog, and reopens it later, I want to remember the location and open the window at the exact same spot. How would I exactly remember that location?

Upvotes: 6

Views: 6766

Answers (5)

Daniel Donnelly
Daniel Donnelly

Reputation: 620

_windowStatesEnum = {
    0x00000000 : Qt.WindowNoState,          #       The window has no state set (in normal state).
    0x00000001 : Qt.WindowMinimized,        #       The window is minimized (i.e. iconified).
    0x00000002 : Qt.WindowMaximized,          #      The window is maximized with a frame around it.
    0x00000004 : Qt.WindowFullScreen,         #      The window fills the entire screen without any frame around it.
    0x00000008 : Qt.WindowActive,             # The window is the active window, i.e. it has keyboard focus.        
}
    
def __setstate__(self, data):
    self.__init__()
    self.setGeometry(data['geometry'])
    self.setWindowState(self._windowStatesEnum[data['window state']])
    
def __getstate__(self):
    return {
        'geometry' : self.geometry(),
        'window state' : int(self.windowState()),
    }    

Upvotes: 0

Ronan Paixão
Ronan Paixão

Reputation: 8695

For that, you can use the saveState(), saveGeometry() resize() and move() methods, in conjunction with the closeEvent() and QSettings mentioned by the other answers. Here is some example, to get the idea:

class MyWindow(QMainWindow):
    def __init__(self, parent):
        QMainWindow.__init__(self, parent)
        self.settings = QSettings("MyCompany", "MyApp")
        self.restoreGeometry(self.settings.value("geometry", ""))
        self.restoreState(self.settings.value("windowState", ""))

    def closeEvent(self, event):
        self.settings.setValue("geometry", self.saveGeometry())
        self.settings.setValue("windowState", self.saveState())
        QMainWindow.closeEvent(self, event)

EDIT:

Updated answer to use PyQt API v2. If using API v1, you have to manually cast the result of settings.value() to a ByteArray like

self.restoreState(self.settings.value("windowState").toByteArray())

I also used the window's own size() and pos(), since I'm already loading the windows from a .ui file. You may set it to defaults before those lines if coding the window from scratch. For the state, I'm defaulting to an empty string, which the function happily accepts as an empty ByteArray and does nothing on the first run.

Upvotes: 11

HansHarhoff
HansHarhoff

Reputation: 2007

Ronan Paixão's answer is almost correct. When attempting this a got the error:

AttributeError: 'NoneType' object has no attribute 'toByteArray'

this is because there is, at first, no saved geometry and state. Additionally the return value is already a QByteArray. This code works for me:

class MyWindow(QMainWindow):
    def __init__(self, parent):
        QMainWindow.__init__(self, parent)
        self.settings = QSettings("MyCompany", "MyApp")
        if not self.settings.value("geometry") == None:
            self.restoreGeometry(self.settings.value("geometry"))
        if not self.settings.value("windowState") == None:
            self.restoreState(self.settings.value("windowState"))
    def closeEvent(self, event):
        self.settings.setValue("geometry", self.saveGeometry())
        self.settings.setValue("windowState", self.saveState())
        QMainWindow.closeEvent(self, event)

Upvotes: 6

thegrinner
thegrinner

Reputation: 12241

It looks like you can use QSettings for this. If you look at the section of the documentation titled Restoring the State of a GUI Application you'll find an example for a main window.

In other words, save the size and location when the user closes the dialog, then next time they open it reload those settings.

Upvotes: 1

Brett Patterson
Brett Patterson

Reputation: 11

You could reimplement the CloseEvent of the dialog (found here in the Qt documentation), and save the appropriate settings using QSettings (docs here).

class MyDialog(QDialog):
    def closeEvent(event):
        settings = QSettings()
        settings.setValue('value1', 1)
        event.accept()

Upvotes: 1

Related Questions