6

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?

user2315
  • 831
  • 5
  • 11
  • 21
  • Take a look at [this](http://stackoverflow.com/questions/1538425/how-to-control-the-position-of-qdialog) question. It looks like standard QT instead if pyQT, but I imagine it'll translate. – thegrinner Jul 05 '12 at 20:37

5 Answers5

11

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.

Ronan Paixão
  • 8,297
  • 1
  • 31
  • 27
6

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)
HansHarhoff
  • 1,917
  • 2
  • 22
  • 32
  • 1
    Changed example to return empty string by default, which fixes the problem more cleanly, since the restore functions accept empty strings. This way I don't need to get values twice. – Ronan Paixão Sep 05 '16 at 03:48
1

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.

Community
  • 1
  • 1
thegrinner
  • 11,546
  • 5
  • 41
  • 64
1

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()
0
_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()),
    }    
MathCrackExchange
  • 595
  • 1
  • 6
  • 25