IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Tkinter Python Discussion :

probleme fonction destroy sous tkinter


Sujet :

Tkinter Python

  1. #1
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2017
    Messages : 4
    Points : 1
    Points
    1
    Par défaut probleme fonction destroy sous tkinter
    Bonjour, je suis en train de faire une version graphique de 2048 et je rencontre un problème.

    Lorsque je souhaite fermer le jeu je passe par un menubar dans lequel j'ai ajouté un onglet " gquit " qui appelle la fonction suivante :


    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    def game_quit():
        global name
        if askyesno("Quit game ?","Are you sure? :("):
            if askyesno("Save ?","Do you want to save your game? "):
                ask_name()
                save_scoreG(grid,lenght)
        fenetre.destroy()
    Lorsque je répond " yes " "yes" aux deux askyesno, une nouvelle fenêtre s'ouvre dans laquelle j'entre mon nom, je clique sur un bouton qui associe le nom entré à ma variable name. Et la fenêtre du widget Entry se ferme grâce au master.destroy() . Cependant, le fenetre.destroy() ne fonctionne pas dans ce cas-ci. Je dois le quitter à la main pour obtenir le message " _tkinter.TclError: can't invoke "destroy" command: application has been destroyed "
    Il semblerait que tkinter ait du mal à gérer deux fenêtres Tk() à la fois, c'est pourquoi j'ai mis la fenêtre du widget Entry en Toplevel(), cependant rien y change.

    Voici les fonctions appelées :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    def ask_name():
        global entry, master
       master = Toplevel()
        master.title("Your Name")
        button=Button(master, text='Input your name and click here', command = get_name, bg= "yellow" )
        usertext= StringVar()
        entry = Entry(master, textvariable=usertext)
        entry.pack()
        button.pack()
        master.mainloop()
     
     
    def get_name():
        global  name, entry, master
        name = str(entry.get())
        master.destroy()
     
     
    def save_scoreG(grid,lenght):
        global name 
        """ Permet la sauvegarde du score dans un fichier nommé score """
        with open('score','a') as s:
            s.write(str(lenght)+':' + name +':'+ str(score(grid,lenght))+'\n')
    Merci à vous

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 778
    Points
    36 778
    Par défaut
    Salut,

    Citation Envoyé par Watazix Voir le message
    Cependant, le fenetre.destroy() ne fonctionne pas dans ce cas-ci. Je dois le quitter à la main pour obtenir le message " _tkinter.TclError: can't invoke "destroy" command: application has been destroyed "
    Si la question est je crée une fenetre principale Tk(), puis lorsque je passe par la séquence master = Toplevel(), master.destroy()... fenetre.destroy() se vautre, c'est pas compliqué de lancer la console Python et de vérifier:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
     
    >>> from tkinter import Toplevel, Tk
    >>> fenetre = Tk()
    >>> w = Toplevel()
    >>> w.destroy()
    >>> fenetre.destroy()
    Bien sûr, si on applique encore .destroy():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    >>> fenetre.destroy()
    Traceback (most recent call last):
      File "<stdin>", line 1, in <module>
      File "Z:\py34-64\lib\tkinter\__init__.py", line 1842, in destroy
        self.tk.call('destroy', self._w)
    _tkinter.TclError: can't invoke "destroy" command: application has been destroyed
    >>>
    Cela devrait vous convaincre que .destroy appliqué à un widget ne s'applique pas à l'application (fenetre).
    Pour le reste, le problème n'est pas dans le code que vous montrez, et comme vous abusez des variables globales, rien ne dit que "master" est le widget attendu lors du .destroy.

    Citation Envoyé par Watazix Voir le message
    Il semblerait que tkinter ait du mal à gérer deux fenêtres Tk() à la fois, c'est pourquoi j'ai mis la fenêtre du widget Entry en Toplevel(), cependant rien y change.
    tkinter le gère très bien... Il faut juste prendre la précaution d'appeler NoDefaultRoot(), histoire de forcer le programmeur à préciser le "master" et en comprendre les implications. Si vous débutez, vous n'en avez pas besoin. Et pour bien vous former, les cours et tutoriels pour apprendre : Python https://python.developpez.com/cours/


    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  3. #3
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2017
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par wiztricks Voir le message

    Cela devrait vous convaincre que .destroy appliqué à un widget ne s'applique pas à l'application (fenetre).
    Merci de la réponse, cependant, je ne saisis pas comment je suis supposé fermer la fenêtre de ce fait.

    Pour le reste, je suis effectivement débutant. Je suis en prepa ingé et j'ai seulement 1h30 d'info par semaine. Autant dire que je ne comprend pas tout à fait l'intégralité de ma version graphique de 2048 que j'ai dû coder... et j'imagine que mes codes doivent piquer aux yeux de certains

    Merci

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 778
    Points
    36 778
    Par défaut
    Citation Envoyé par Watazix Voir le message
    Merci de la réponse, cependant, je ne saisis pas comment je suis supposé fermer la fenêtre de ce fait.
    La première chose à faire est de vérifier ce qu'est master après la création du Toplevel et ce qu'il est devenu juste avant master.destroy().
    Pour çà, la fonction "print" devrait vous aider.
    S'ils sont différents, çà veut dire que cette variable globale est utilisée pour autre chose. Vous pourriez essayer de donner un autre nom à la variable qui sert à stocker/récupérer la Toplevel.
    S'ils sont égaux, c'est pas master.destroy() suivi de fenetre.destroy() qui pose problème mais plusieurs appels à fenetre.destroy() - et çà se passe dans le code que vous ne montrez pas.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  5. #5
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2017
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    https://github.com/sdescamp/20488

    J'ai déjà essayé de modifier le nom ( master ) en fen et rien y fait...

    Voici le lien de mon projet, pour lancer le jeu, il faut ouvrir graphical_2048.py via idle et run.
    Pour avoir l'erreur, il faut aller dans Game > Quit > Yes > Yes > Entrer n'importe quoi dans la case tant et appuyer sur le bouton. Dans ce cas seule le widget se fermera et lorsqu'on ferme l'appli manuellement, l'erreur pop dans le shell.

    Je ne comprends pas où il pourrait y avoir une gêne, d'autant plus que si on répond no à la seconde question le programme se fermera sans problèmes. Peut-il y avoir une erreur en raison de l'utilisation de plusieurs mainloop dans un programme ?


    Watazix

  6. #6
    Nouveau Candidat au Club
    Homme Profil pro
    Étudiant
    Inscrit en
    Mai 2017
    Messages
    4
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Pas de Calais (Nord Pas de Calais)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Mai 2017
    Messages : 4
    Points : 1
    Points
    1
    Par défaut
    Citation Envoyé par Watazix Voir le message
    Peut-il y avoir une erreur en raison de l'utilisation de plusieurs mainloop dans un programme ?

    Bon en tournant autour du mainloop je me suis rendu compte que je pouvais utiliser la fonction .quit pour mon master, ce qui me permet semblerait-il de destroy la fenetre ensuite.

  7. #7
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 287
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 287
    Points : 36 778
    Points
    36 778
    Par défaut
    Citation Envoyé par Watazix Voir le message
    Je ne comprends pas où il pourrait y avoir une gêne, d'autant plus que si on répond no à la seconde question le programme se fermera sans problèmes. Peut-il y avoir une erreur en raison de l'utilisation de plusieurs mainloop dans un programme ?
    Le problème est qu'on ne sort de "mainloop" qu'avec un "quit" ou la destruction de la fenêtre principale.
    Lorsque vous sortez du jeu via game_quit, fenetre.destroy n'est pas atteint (master.mainloop bloque). Lorsqu'on force la fermeture de la fenêtre principale, çà fait un "quit" de cette mainloop et l'exécution de game_quit bloqué jusque là se termine et le fenetre.destroy fout la grouille.
    En fait vous avez écrit "master.mainloop" pour attendre que la fenêtre de dialogue (Toplevel) se ferme.
    Soit vous forcer un .quit pour en sortir, soit vous utiliser fenetre.wait_window(master) - qui fait exactement cela.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

Discussions similaires

  1. PERL/Tk: probleme pour lancer deux fois la fonction destroy
    Par seben dans le forum Interfaces Graphiques
    Réponses: 2
    Dernier message: 04/03/2009, 15h53
  2. [PG FONCTION C] Probleme palloc.h sous windows
    Par VASAPANCH dans le forum PostgreSQL
    Réponses: 3
    Dernier message: 10/07/2008, 10h02
  3. Réponses: 8
    Dernier message: 07/07/2007, 12h39
  4. Réponses: 6
    Dernier message: 08/12/2006, 14h59
  5. Réponses: 2
    Dernier message: 02/12/2005, 10h53

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo