Dialog wird mit show() nicht angezeigt

Python und das Qt-Toolkit, erstellen von GUIs mittels des Qt-Designers.
Antworten
Amelie
User
Beiträge: 16
Registriert: Montag 7. März 2011, 14:48

Hallo,
Ich habe ein Problem mit dem Anzeigen von Fenstern mit PyQt4.
Ich habe zuerst ein QMainWindow, von dem aus über Weiter/Zurück Buttons nacheinander 3 QDialogs geöffnet werden um am Ende der Folge etwas zu berechnen. Von QMainWindow auf QDialog_1 funktioniert alles einwandfrei, allerdings, wenn ich in Dialog_1 'weiter' klicke, wird Dialog_2 nicht angezeigt. Wenn ich hier allerdings show() mit exec_() ersetze wird es gezeigt (aber das will ich natürlich nicht, weil der Benutzer die Kontrolle behalten soll). Hat das mit dem Aufrufen eines neuen QDialogs aus einem QDialog und nicht QMainWindow zu tun? Wo sonst könnte das Problem stecken?

Code: Alles auswählen

# in class MainWindow
def abbrechen(self) :
    if QMessageBox.question(None, 'MyPlugin', 'Wollen Sie den Vorgang wirklich abbrechen?', 
      QMessageBox.Yes, QMessageBox.No) == QMessageBox.Yes :
      self.ui.close()
    else : 
      pass
   
  def weiter(self) :
    self.ui.hide()
    QDialog_1(self.iface, self.layer)

Code: Alles auswählen

# in class Dialog_1
[...]
# Set up the user interface from Designer
    code_dir = os.path.dirname(os.path.abspath(__file__))
    self.Dialog_1_ui= loadUi(os.path.join(code_dir, "Ui_Dialog_1.ui"))
    self.Dialog_1_ui.show()
[...]
  def abbrechen(self) :
    [...]
  def weiter(self) :
    self.Dialog_1_ui.close()
    Dialog_2(self.iface, self.layer)
  def zurueck(self) :  
    self.Dialog_1_ui.close()
    MainWindow(self.iface)

Code: Alles auswählen

# in class Dialog_2        
# Set up the user interface from Designer
        code_dir = os.path.dirname(os.path.abspath(__file__))
        self.Dialog_2_ui = loadUi(os.path.join(code_dir, "Ui_Dialog_2.ui"))
        self.Dialog_2_ui.show()
[...]
Zuletzt geändert von Amelie am Montag 11. April 2011, 10:21, insgesamt 1-mal geändert.
BlackJack

@Amelie: In dem Code für `Dialog_2` steht wieder `self.Dialog_1_ui`!? Das sollte nicht das Problem sein, aber es ist vielleicht ein wenig irreführend.

Ansonsten denke ich dass man aus dem gezeigten Teil nichts ersehen kann. Was machst Du denn nach dem `show()`? Wird da auch die Kontrolle an die GUI-Hauptschleife zurück gegeben oder läuft da weitere Code von Dir ab? Kannst Du ein minimales, lauffähiges Beispiel zeigen was das Problem aufweist?

Last but not least klingt das vom Ablauf her mit den Vor- und Zurück-Schaltflächen nach einem "Wizard". Für so etwas gibt schon ein spezielles Widget `QWizard`.
Amelie
User
Beiträge: 16
Registriert: Montag 7. März 2011, 14:48

BlackJack hat geschrieben:@Amelie: In dem Code für `Dialog_2` steht wieder `self.Dialog_1_ui`!? Das sollte nicht das Problem sein, aber es ist vielleicht ein wenig irreführend.
Das war am Eintrag geschlampert, jetzt aber richtig gestellt.
BlackJack hat geschrieben:Ansonsten denke ich dass man aus dem gezeigten Teil nichts ersehen kann. Was machst Du denn nach dem `show()`? Wird da auch die Kontrolle an die GUI-Hauptschleife zurück gegeben oder läuft da weitere Code von Dir ab? Kannst Du ein minimales, lauffähiges Beispiel zeigen was das Problem aufweist?
Die Kontrolle sollte vorerst im Dialog bleiben, hier werden verschiedene Slots/Signale geschalten um dann wieder über weiter/abbrechen/zurück zum nächsten Fenster zu gelangen. Wenn ich z.B. eine QMessageBox einfüge, bleibt Dialog_2 dahinter göffnet, bis die Box geschlossen wird.
BlackJack hat geschrieben:Last but not least klingt das vom Ablauf her mit den Vor- und Zurück-Schaltflächen nach einem "Wizard". Für so etwas gibt schon ein spezielles Widget `QWizard`.
Dieser Tipp sieht sehr gut aus, das ist genau das, was ich erreichen möchte. Ich werde mich heute Nachmittag näher damit beschäftigen. Deswegen lass ich den Beispielcode im Moment auch erstmal weg.
Danke!
lunar

Was das ursprüngliche Problem angeht, so liegt dies wahrscheinlich daran, dass der zweite Dialog nur an einen lokalen Namen gebunden wird, und kein Vater-Objekt hat. In der Folge löscht der Python-GC den Dialog beim Austritt aus der Funktion, noch vor der Rückkehr in die Ereignisschleife, so dass der Dialog folglich zum Zeitpunkt, an dem er angezeigt werden sollte, gar nicht mehr existiert.
Amelie
User
Beiträge: 16
Registriert: Montag 7. März 2011, 14:48

Amelie hat geschrieben:...so dass der Dialog folglich zum Zeitpunkt, an dem er angezeigt werden sollte, gar nicht mehr existiert.
Aber er wird ja für einen kurzen Moment angezeigt. Wenn man sein Schließen durch eine eingeschaltete QMessageBox im Vordergund verzögert, sieht man ihn auch im Hintergrund (auch, dass es genau der Dialog ist, der offen sein und bleiben sollte)
BlackJack

@Amelie: Das ändert allerdings nicht viel an lunar's Vermutung. Dann wird der Dialog eben kurz angezeigt -- wenn die `show()`-Methode darauf aufgerufen wird, existiert das Objekt ja noch. Aber kurz danach ist es halt weg und wird dann anscheinend auch nicht mehr angezeigt. Da könnten IMHO auch schlimmere Dinge passieren als einfach keine Anzeige mehr. Wenn der darunter liegende C++-Code auf ein nicht mehr existierendes C++-Objekt zugreifen möchte, könnte auch das ganze Programm hart abstürzen.

Bei GUI-Toolkits muss man leider immer ein bisschen darauf achten, dass die bequeme automatische Speicherverwaltung nur in Python uneingeschränkt gilt. Wenn über Python externer Code angesprochen wird, kann der manchmal Anforderungen an Objekte und deren "Lebenszeit" stellen, von denen die Python-Laufzeitumgebung nichts weiss.
Antworten