Wie wiederhole ich einen Dialog mit PyGTK / Gtkbuilder?

8

Ich habe eine PyGTK-Anwendung erstellt, die einen Dialog anzeigt, wenn der Benutzer eine Schaltfläche drückt. Der Dialog wird in meine __init__ Methode geladen mit:

%Vor%

Im Event-Handler wird der Dialog mit dem Befehl self.myDialog.run() angezeigt, dies funktioniert aber nur einmal, weil nach run() der Dialog automatisch zerstört wird. Wenn ich die Schaltfläche ein zweites Mal klicke, stürzt die Anwendung ab.

Ich habe gelesen, dass es eine Möglichkeit gibt, show() anstelle von run() zu verwenden, wo der Dialog nicht zerstört wird, aber ich denke, das ist nicht der richtige Weg für mich, weil ich möchte, dass sich der Dialog modal verhält Geben Sie die Steuerung nur dann an den Code zurück, wenn der Benutzer sie geschlossen hat.

Gibt es eine einfache Möglichkeit, einen Dialog wiederholt mit der run() -Methode mit gtkbuilder anzuzeigen? Ich habe versucht, den gesamten Dialog mit dem gtkbuilder neu zu laden, aber das schien nicht wirklich zu funktionieren, dem Dialog fehlten alle untergeordneten Elemente (und ich würde es vorziehen, den Builder nur einmal am Anfang des Programms verwenden zu müssen).

[LÖSUNG] (bearbeitet)
Wie in der Antwort unten gezeigt, macht die Verwendung von hide() den Trick. Ich dachte zuerst, du hättest das "delete-event" noch abfangen müssen, aber das ist in der Tat nicht nötig. Ein einfaches Beispiel, das funktioniert, ist:

%Vor%     
Julian 11.01.2011, 11:56
quelle

3 Antworten

4

Lesen Sie die Dokumentation zu Dialog.run() . Der Dialog wird nicht automatisch zerstört. Wenn du hide() itest, wenn die run() Methode beendet wird, dann solltest du run() so oft wie du willst.

Alternativ können Sie festlegen, dass der Dialog in Ihrer Erstellungsdatei modal ist, und dann nur show() it. Dadurch wird ein ähnlicher Effekt erzielt, aber nicht ganz derselbe wie run() - weil run() eine zweite Instanz der Haupt-GTK-Schleife erstellt.

BEARBEITEN

Der Grund dafür, dass Sie einen Segmentierungsfehler erhalten, wenn Sie keine Verbindung zum delete-event -Signal herstellen, besteht darin, dass Sie zweimal auf die Schließen-Schaltfläche klicken. Hier ist was passiert:

  1. Sie klicken auf "Run Dialog", dies ruft die run() Methode des Dialogs auf.
  2. Der modale Dialog erscheint und startet eine eigene Hauptschleife.
  3. Sie klicken auf die Schaltfläche zum Schließen. Die Hauptschleife des Dialogfelds wird beendet, aber da run() das normale Verhalten der Schließen-Schaltfläche außer Kraft setzt, wird das Dialogfeld nicht geschlossen. Es ist auch nicht versteckt, also hängt es herum.
  4. Sie fragen sich, warum der Dialog immer noch da ist und klicken Sie erneut auf die Schaltfläche zum Schließen. Da run() nicht mehr aktiv ist, wird das normale Verhalten der Schließen-Schaltfläche ausgelöst: Der Dialog ist zerstört.
  5. Sie klicken erneut auf "Run Dialog", um die Methode run() des zerstörten Dialogs aufzurufen. Absturz!

Wenn Sie sicherstellen, dass hide() der Dialog nach Schritt 3 ist, dann sollte alles funktionieren. Es besteht keine Notwendigkeit, eine Verbindung zum delete-event -Signal herzustellen.

    
ptomato 11.01.2011, 22:14
quelle
2

Ich habe gerade einige Zeit damit verbracht, dies herauszufinden. Das erneute Abrufen desselben Objekts aus einem Builder erstellt keine neue Instanz des Objekts, sondern gibt nur einen Verweis auf das alte (zerstörte) Objekt zurück. Wenn Sie jedoch eine neue Builder-Instanz erstellen und Ihre Datei in den neuen Builder laden, wird eine neue Instanz erstellt.

So sieht meine Dialog-Erstellungsfunktion ungefähr so ​​aus:

%Vor%

Beachten Sie, dass ich für eine Antwort mit run () in diesem Fall nicht blockiere, weil ich Twist benutze, aber es sollte äquivalent sein.

    
bj0 16.02.2011 01:50
quelle
0

Ihr Dialog sollte nur einmal ausgeführt werden. Unter der Annahme, dass ein Menüelement den Dialog auslöst, sollte der Code etwa so aussehen:

%Vor%

dialog.run() ist eine blockierende Hauptschleife, die zurückkehrt, wenn der Dialog eine Antwort sendet. Dies geschieht normalerweise über die Schaltflächen Ok und Abbrechen. Wenn dies geschieht, ist der Dialog beendet und muss zerstört werden.

Um den Dialog wiederholt anzuzeigen, sollte der Benutzer denselben Arbeitsablauf befolgen (im obigen Beispiel würde das Klicken auf einen Menüeintrag sein). Der Dialog ist in __init__ für das Einrichten verantwortlich. Wenn Sie den Dialog hide() haben, haben Sie das Problem, mit diesem Dialog zu kommunizieren, damit er auch dann mit dem Rest der Anwendung auf dem neuesten Stand bleibt, wenn er ausgeblendet ist .

Einer der Gründe, warum manche Leute den Dialog "wiederholt ausführen" wollen, ist, dass der Benutzer ungültige Informationen eingegeben hat und Sie dem Benutzer die Möglichkeit geben möchten, ihn zu korrigieren. Dies muss im Antwort-Signal-Handler des Dialogs behandelt werden. Die Reihenfolge der Ereignisse in einem Dialogfeld ist:

  1. Der Benutzer drückt die Ok-Taste
  2. Dialog sendet die Antwort gtk.RESPONSE_OK (-5)
  3. Dialog ruft den Handler für das Antwortsignal
  4. auf
  5. Dialog ruft den Handler für die Ok-Schaltfläche
  6. auf
  7. Die Methode run() gibt die Antwort
  8. zurück

Um die Schritte 4 und 5 zu verhindern, muss der Antworthandler das Antwortsignal unterdrücken. Dies wird wie folgt erreicht:

%Vor%     
Jon 22.01.2011 10:02
quelle

Tags und Links