Größe und Position speichern

Hier werden alle anderen GUI-Toolkits sowie Spezial-Toolkits wie Spiele-Engines behandelt.
Antworten
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Hi PyQt'ler, :-)

Ich programmiere gerade eine Mdi Anwendung.

Ich bin dabei mit der Klasse QSettings rum zu spielen, also das speichern der Fenster Einstellungen(Größe und Position).
Es soll also die Position und Größe des Hauptfenster's und aller Unterfenster über ein QSettings Objekt gespeichert werden.
Bei meinem Hauptfenster klappt das, allerdings nicht bei meinem Unterfenster(Reisehelfer genannt).

Gibt es eine Gesamtübersicht aller Signale?
Vielleicht habe ich einfach nur die falschen Signale getestet.
Ich will dass das Unterfenster beim schliessen seine Größe und Position speichert über QSettings genau wie beim Hauptfenster.
Was mache ich falsch?
Kann mir einer erklären, was Zeile 23 und 24 in hauptfenster.py bewirken?

Hier ein Ausschnitt meiner aktuellen Sourcen,
Hauptfenster,

Code: Alles auswählen

#!/usr/bin/env python
#
#hauptfenster.py
#

import sys
from PyQt4 import QtCore, QtGui
from reisehelfer import *


class MainWindow(QtGui.QMainWindow):
    def __init__(self, parent=None):
        QtGui.QMainWindow.__init__(self, parent)
        
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        
        self.workspace = QtGui.QWorkspace()
        self.setCentralWidget(self.workspace)
        
        self.connect(self.workspace, QtCore.SIGNAL("windowActivated(QWidget *)"), 
                     self.updateMenus)
        self.windowMapper = QtCore.QSignalMapper(self)
        self.connect(self.windowMapper, QtCore.SIGNAL("mapped(QWidget *)"),
                     self.workspace, QtCore.SLOT("setActiveWindow(QWidget *)"))
        
        self.createActions()
        self.createMenus()
        self.createStatusBar()
        self.updateMenus()

        self.readSettings()

        self.setWindowTitle(self.tr("DSA 4 Meisterhilfe"))
        
...

    def updateMenus(self):
        pass

    def readSettings(self):
        settings = QtCore.QSettings("SettingHauptFenster", "DSA 4 Meisterhilfe")
        pos = settings.value("pos", QtCore.QVariant(QtCore.QPoint(200, 800))).toPoint()
        size = settings.value("size", QtCore.QVariant(QtCore.QSize(1200, 800))).toSize()
        self.move(pos)
        self.resize(size)
        

    def writeSettings(self):
        settings = QtCore.QSettings("SettingHauptFenster", "DSA 4 Meisterhilfe")
        settings.setValue("pos", QtCore.QVariant(self.pos()))
        settings.setValue("size", QtCore.QVariant(self.size()))

...

und Unterfenster,

Code: Alles auswählen

#!/usr/bin/env python
#
#reisehelfer.py
#

import sys
from PyQt4 import QtCore, QtGui


class ReiseHelfer(QtGui.QWidget):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        
        self.setAttribute(QtCore.Qt.WA_DeleteOnClose)
        
        self.connect(self, QtCore.SIGNAL("close(QWidget *)"), self.writeSettings)
        
        self.setWindowTitle(self.tr("Reisehelfer"))

        self.readSettings()

...

    def readSettings(self):
        settings = QtCore.QSettings("SettingUnterFenster", "DSA 4 Meisterhilfe")
        pos = settings.value("pos", QtCore.QVariant(QtCore.QPoint(50, 50))).toPoint()
        size = settings.value("size", QtCore.QVariant(QtCore.QSize(1100, 700))).toSize()
        self.move(pos)
        self.resize(size)
        

    def writeSettings(self):
        settings = QtCore.QSettings("SettingUnterFenster", "DSA 4 Meisterhilfe")
        settings.setValue("pos", QtCore.QVariant(self.pos()))
        settings.setValue("size", QtCore.QVariant(self.size()))

...

Zuletzt geändert von feldmaus am Mittwoch 5. März 2008, 14:48, insgesamt 2-mal geändert.
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Ich muss nochmal genau schauen welches Attribut, aber damit Größe und Position gespeichert werden können müssen die Namen eindeutig sein. Wenn alle "Reisehelfer" heißen geht es nicht.

Ich weiß allerdings nicht ob das überhaupt bei MDI Unterfenstern funktioniert. Bisher weiß ich nur von den Dockwidgets und Toolbars die automatisch gespeichert werden

PS: Du spielst DSA?

PPS: Ach ja, hast du der app einen Namen gegeben? Das ist anscheinend auch eine Voraussetzung damit das funktioniert.

Code: Alles auswählen

app=QApplication(sys.argv)
app.setOrganisationName("Org")
app.setOrganisationDomain("org.org")
app.setApplicationName("Reisehelfer")
Benutzeravatar
mkesper
User
Beiträge: 919
Registriert: Montag 20. November 2006, 15:48
Wohnort: formerly known as mkallas
Kontaktdaten:

Was ich an MDI-Anwendungen hasse, sind diese "modalen" Fenster, die meist total überflüssig sind, das Leben aber unnötig umständlich machen.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

burli hat geschrieben: PS: Du spielst DSA?
Yes, super Game :P
burli hat geschrieben: PPS: Ach ja, hast du der app einen Namen gegeben?
Mein Hauptfenster hat folgende Attribute,
  • ApplicationName="DSA 4 Meisterhilfe"
    OrganisationName="SettingHauptFenster"
    WindowTitle="DSA 4 Meisterhilfe"
Und mein Unterfenster Reisehelfer hat,
  • ApplicationName="DSA 4 Meisterhilfe"
    OrganisationName="SettingUnterFenster"
    WindowTitle="Reisehelfer"
Das Attribut OrganisationDomain habe ich nicht gesetzt.

Mein Hauptfenster übernimmt die alten Einstellungen ja auch, also kann ich ja nicht ganz falsch liegen.

Ich versuche gerade mit dem Debugger pdb nach Fehlern zu schauen. Ich schaffe es allerdings nicht während des debuggens das Unterfenster zu starten. Das Menü des Hauptfensters ist im Debug Modus wie eingefroren. Ich komme zwar mit step bis das Hauptprogramm gestartet ist, dann weiß ich aber nicht mehr weiter. Ich nutze Emacs.
Hat da Jemand einen Tipp?
Zuletzt geändert von feldmaus am Mittwoch 5. März 2008, 11:45, insgesamt 1-mal geändert.
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

feldmann_markus hat geschrieben:Ich versuche gerade mit dem Debugger pdb nach Fehlern zu schauen. Ich schaffe es allerdings nicht während des debuggens das Unterfenster zu starten. Das Menü des Hauptfensters ist im Debug Modus wie eingefroren. Ich komme zwar mit step bis das Hauptprogramm gestartet ist, dann weiß ich aber nicht mehr weiter.
Ja, weil der Debugger das Programm anhält, und wenn das Programm angehalten ist, funktioniert die Mainloop von Qt ja nicht, also werden auch die Fenster nicht aktualisiert.
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

feldmann_markus hat geschrieben: Mein Hauptfenster übernimmt die alten Einstellungen ja auch, also kann ich ja nicht ganz falsch liegen.
Haben die Unterfenster alle den gleichen Namen? Ich weiß wie gesagt nicht ob das auch für MDI gilt, aber für Docked Widgets und Toolbars weiß ich das jedes Widget einen einmaligen Namen haben muss
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

burli hat geschrieben: Haben die Unterfenster alle den gleichen Namen?
Ich nehme an, dass du mit Namen den Fenstertitel meinst.
Mein Hauptfenster hat den Fenstertitel "DSA 4 Meisterhilfe" und mein Unterfenster hat den Fenstertitel "Reisehelfer". Alle Unterfenster bekommen einen eigenen Namen.
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Leonidas hat geschrieben: Ja, weil der Debugger das Programm anhält, und wenn das Programm angehalten ist, funktioniert die Mainloop von Qt ja nicht, also werden auch die Fenster nicht aktualisiert.
Mit next läuft die Anwendung weiter im Gegensatz zu step, allerdings komm ich dann nicht mehr dazu mir den Ablauf genauer anzuschauen.
Wie kann ich mir den Vorgang beim erstellen in pdb trotzdem genauer angucken?
Oder geht das nicht mit pdb?
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

feldmann_markus hat geschrieben: Wie kann ich mir den Vorgang beim erstellen in pdb trotzdem genauer angucken?
Oder geht das nicht mit pdb?
Ok es geht. Man kann erst einige unwichtige Funktionen mit next überspringen und wenn es ernst wird muss man mit step weiter gehen. :lol:

Dabei ist mir dann aufgefallen, das er die Signal/Slot Connection meines Unterfensters gar nicht berücksichtigt.
Dafür sehe ich 2 Möglichkeiten,
1. Entweder habe ich das falsche Ereignis gewählt
2. Oder das Ereignis wird nicht durchgelassen
Kann mir da einer einen Tipp geben?
Ich verwende in meinem Hauptfenster den QSignalMapper, wo ich immer noch nicht weiß, was der macht.
Wie kann ich das Ereignis in pdb abfangen?
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Du solltest an den Stellen die dich interessieren Breakpoints setzen. Dann kannst du die Applikation normal starten und wenn du zb ein Menu auswählst oder irgendwas anderes machst was du halt debuggen willst hält das Programm an der entsprechenden Stelle an
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

burli hat geschrieben:Du solltest an den Stellen die dich interessieren Breakpoints setzen.
Danke für die Idee werde es beherzigen.
Wenn ich mein Unterfenster schliesse wird folgendes ausgeführt,

Code: Alles auswählen

--Call--
> /home/markus/eigenedateien/RPG/DSA/projekte/meisterhilfe/module/sys/hauptfenster.py(56)updateMenus()
-> def updateMenus(self):
(Pdb) > /home/markus/eigenedateien/RPG/DSA/projekte/meisterhilfe/module/sys/hauptfenster.py(57)updateMenus()
-> pass
(Pdb) s
--Return--
> /home/markus/eigenedateien/RPG/DSA/projekte/meisterhilfe/module/sys/hauptfenster.py(57)updateMenus()->None
-> pass
Anscheinend wurde meine SIGNAL/SLOT Verbindung in Zeile 21 von "hauptfenster.py" ausgeführt, beim schliessen. Es ist zwar richtig das das Unterfenster beim schliessen, gleichzeitig auch aktiviert wird beim schliessen, aber er müßte doch trotzdem meine SIGNAL/SLOT Verbindung in Zeile 17 von "reisehelfer.py" ausführen?
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Meine Vermutung liegt ganz stark beim QSignalMapper.
Nur wie stelle ich den richtig ein, sodaß ein close() Ereignis zu einem Ausführen meiner Methode writteSettings() in reisehelfer.py führt?
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

Den muss man nicht "einstellen". Beim Beenden der Anwendung wird ein SIGNAL erzeugt. An dieses Signal kannst du beliebig viele SLOTs hängen.

Du musst nur jeden Slot mit connect() an das Signal hängen
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

burli hat geschrieben:Den muss man nicht "einstellen".
Und welche Rolle hat der QSignalMapper ?
Laut Doku soll er Signale mappen, sprich Signale umleiten?
burli
User
Beiträge: 1156
Registriert: Dienstag 9. März 2004, 18:22

feldmann_markus hat geschrieben:
burli hat geschrieben:Den muss man nicht "einstellen".
Und welche Rolle hat der QSignalMapper ?
Laut Doku soll er Signale mappen, sprich Signale umleiten?
Hm, ich hab das leider nur mal überfliegen können. Scheint man nur in Verbindung mit MDI zu verwenden. Ich vermute es hat was damit zu tun das die Signals an das jeweils aktuelle MDI Fenster geleitet werden damit sich nicht jedesmal alle Fenster angesprochen fühlen. Aber die Quit Message sollte denke ich an alle MDI Fenster und bräuchte somit auch nicht über den Mapper zu laufen.

Das ist jetzt nur meine Vermutung. Kann auch falsch liegen
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Keines der folgenden SIGNAL/SLOT Verbindungen funktioniert,

Code: Alles auswählen

self.connect(self, QtCore.SIGNAL("closed(QWidget *)"), self.writeSettings)
self.connect(self, QtCore.SIGNAL("close(QWidget *)"), self.writeSettings)
self.connect(self, QtCore.SIGNAL("quit(QWidget *)"), self.writeSettings)
self.connect(self, QtCore.SIGNAL("destroyed(QWidget *)"), self.writeSettings)
feldmaus
User
Beiträge: 284
Registriert: Donnerstag 12. Oktober 2006, 16:48

Ich habe in der Doku [url=file:///usr/share/doc/python-qt4-doc/html/qsettings.html#restoring-the-state-of-a-gui-application]Qt4 lokale Doku zu QSettings[/url]
was interessantes gelesen, ich weiß aber nicht ob ich das ernst nehmen muss?
  • The readSettings() and writeSettings() functions must be called from the main window's constructor and close event handler as follows:

    MainWindow.MainWindow()
    {
    ...
    readSettings();
    }

    void MainWindow.closeEvent(QCloseEvent *event)
    {
    if (userReallyWantsToQuit()) {
    writeSettings();
    event->accept();
    } else {
    event->ignore();
    }
    }
Können die readSettings und writeSettings Methode wirklich nur so aufgerufen werden und nciht etwa über Signale?
Antworten