Question

Je l'ai créé une application PyGTK qui affiche une boîte de dialogue lorsque l'utilisateur appuie sur un bouton. La boîte de dialogue est chargé dans ma méthode de __init__ avec:

builder = gtk.Builder()
builder.add_from_file("filename")
builder.connect_signals(self) 
self.myDialog = builder.get_object("dialog_name")

Dans le gestionnaire d'événements, la boîte de dialogue est affichée avec la commande self.myDialog.run(), mais cela ne fonctionne qu'une fois, car après run() la boîte de dialogue est automatiquement détruit. Si je clique sur le bouton une deuxième fois, la plante demande.

Je lis qu'il ya un moyen d'utiliser show() au lieu de run() où la boîte de dialogue n'est pas détruite, mais je sens que ce n'est pas la bonne façon pour moi parce que je voudrais la boîte de dialogue de se comporter de façon modale et de rendre le contrôle à la le code seulement après que l'utilisateur a fermé il.

Y at-il un moyen simple de montrer à plusieurs reprises une boîte de dialogue en utilisant la méthode run() en utilisant GtkBuilder? J'ai essayé de recharger le dialogue tout en utilisant le GtkBuilder, mais cela ne semblait pas vraiment au travail, la boîte de dialogue manquait tous les éléments enfants (et je préférerais avoir à utiliser le générateur qu'une seule fois, au début du programme).


[SOLUTION] (modifié)
Comme l'a souligné la réponse ci-dessous, en utilisant hide() fait l'affaire. Je pensais d'abord vous encore besoin pour attraper le « delete-event », mais en fait pas nécessaire. Un exemple simple qui fonctionne est:


import pygtk
import gtk

class DialogTest:

    def rundialog(self, widget, data=None):
        self.dia.show_all()
        result = self.dia.run() 
        self.dia.hide()


    def destroy(self, widget, data=None):
        gtk.main_quit()

    def __init__(self):
        self.window = gtk.Window(gtk.WINDOW_TOPLEVEL)
        self.window.connect("destroy", self.destroy)

        self.dia = gtk.Dialog('TEST DIALOG', self.window, 
           gtk.DIALOG_MODAL  | gtk.DIALOG_DESTROY_WITH_PARENT)
        self.dia.vbox.pack_start(gtk.Label('This is just a Test'))


        self.button = gtk.Button("Run Dialog")    
        self.button.connect("clicked", self.rundialog, None)
        self.window.add(self.button)
        self.button.show()
        self.window.show()



if __name__ == "__main__":
    testApp = DialogTest()
    gtk.main()
Était-ce utile?

La solution

En fait, lisez la documentation sur Dialog.run(). La boîte de dialogue est pas automatiquement détruit. Si vous hide() quand la sortie de la méthode de run(), alors vous devriez être en mesure de run() autant de fois que vous le souhaitez.

Vous pouvez définir la boîte de dialogue pour être modale dans votre fichier de constructeur, et puis juste show() il. Cela permettra d'atteindre un effet qui est similaire, mais pas tout à fait la même chose que run() -. Parce run() crée une deuxième instance de la boucle principale GTK

EDIT

La raison pour laquelle vous obtenez une erreur de segmentation si vous ne connectez pas au signal de delete-event est que vous cliquez sur le bouton Fermer deux fois. Voici ce qui se passe:

  1. Vous cliquez sur « Exécuter dialogue », ce appelle la méthode run() de la boîte de dialogue.
  2. La boîte de dialogue modale apparaît et commence sa propre boucle principale.
  3. Vous cliquez sur le bouton Fermer. sorties principales de la boucle de la boîte de dialogue, mais depuis run() Bloque le comportement normal du bouton de fermeture, la boîte de dialogue ne sont pas fermées. Il est également pas caché, il se bloque autour.
  4. Vous vous demandez pourquoi le dialogue est toujours là et cliquez à nouveau sur le bouton Fermer. Depuis run() n'est plus actif, le comportement normal du bouton de fermeture est déclenchée:. La boîte de dialogue est détruit
  5. Vous cliquez sur « Exécuter Dialog » à nouveau, qui tente d'appeler la méthode run() de la boîte de dialogue détruite. Crash!

Donc, si vous assurez-vous de la boîte de dialogue hide() après l'étape 3, puis tout devrait fonctionner. Il n'y a pas besoin de se connecter au signal delete-event.

Autres conseils

Je viens de passer un peu de temps à comprendre ce. Re-aller chercher le même objet d'un constructeur ne crée pas une nouvelle instance de l'objet, mais seulement renvoyer une référence à l'objet ancien (détruit). Si vous créez une nouvelle instance de constructeur, cependant, et chargez votre fichier dans le nouveau constructeur, il va créer une nouvelle instance.

Donc, ma fonction de création de dialogue ressemble à quelque chose comme ceci:

def create():
    builder = gtk.Builder()
    builder.add_from_file('gui/main.ui')

    dlg = builder.get_object('new_dialog')

    def response_function(dialog, response_id):
        ... do stuff ...
        dialog.destroy()

    dlg.connect('response', response_function)
    dlg.show_all()

Notez que je ne suis pas le blocage pour une réponse à l'exécution () dans ce cas parce que je me sers tordu, mais il devrait être équivalent.

Votre dialogue ne devrait avoir besoin d'exécuter une fois. En supposant un des déclencheurs de l'élément de menu de la boîte de dialogue, le code devrait ressembler à ceci:

def on_menu_item_clicked(self, widget, data=None):
    dialog = FunkyDialog()
    response = dialog.run()

    if response = gtk.RESPONSE_OK:
        // do something with the dialog data

    dialog.destroy()

dialog.run() est une principale boucle de blocage qui le retour lorsque la boîte de dialogue envoyer une réponse. Cela se fait normalement via les boutons OK et Annuler. Lorsque cela se produit, la boîte de dialogue est terminé et doit être détruit.

Pour afficher la boîte de dialogue à plusieurs reprises, l'utilisateur doit suivre le même flux de travail (dans l'exemple ci-dessus, qui serait en cliquant sur un élément de menu). La boîte de dialogue est responsable, en __init__, pour lui-même la mise en place. Si vous hide() la boîte de dialogue, vous avez le problème de communication avec cette boîte de dialogue de sorte qu'il reste une mise à jour avec le reste de l'application même quand il est caché .

L'une des raisons pour lesquelles certaines personnes veulent « lancer la boîte de dialogue à plusieurs reprises » est parce que l'utilisateur a entré des informations non valides, et que vous voulez donner à l'utilisateur la possibilité de le corriger. Celle-ci doit être traitée dans le gestionnaire de signal de réponse de la boîte de dialogue. L'ordre des événements dans une boîte de dialogue est:

  1. L'utilisateur pousse physiquement le bouton Ok
  2. Dialogue envoie le gtk.RESPONSE_OK de réponse (-5)
  3. appelle le gestionnaire de dialogue pour le signal de réponse
  4. Dialog appelle le gestionnaire pour le bouton Ok
  5. Dialog méthode de run() renvoie la réponse

Pour éviter les étapes 4 et 5 de se produire, le gestionnaire de réponse doit supprimer le signal de réponse. Ceci est réalisé comme suit:

def on_dialog_response(self, dialog, response, data=None:
    if response == gtk.RESPONSE_OK:
        if data_is_not_valid:
            # Display an error message to the user

            # Suppress the response
            dialog.emit_stop_by_name('response')
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top