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 :

Instances mortes de type None


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut Instances mortes de type None
    Salut les Pythons,
    Je n'arrive pas a effacer des widget restaurer avec des nouvelles instances et avec la une méthode d'insertion analogue, après effacage. Dans le dico ou j'ai mes nouvelles instances (restaurer) sont de type None: Quand j'appelle la variable elles y sont les nouvelles instances mais quand je fait:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print dico_new_instance.keys()
    il s'affiche
    J'en déduit que les instances sont de type None (morte) et donc plus manipulable, pour la suite de mon programme.

    le programe suivant simplifie mon problème (et marche lui) et vous guide sur ma marche a suivre dans un programme plus complexe oû peut etre les instances meurent car il fait 2000 lignes:
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
     
    # -*- coding: utf-8 -*-
    from Tkinter import *
     
    def test_1() :
      global b
      instances={}#normalement dans le contructeur de la classe 
      var=IntVar()
      chk=Checkbutton(b, text="test", variable=var).pack()
      restore.append('test_2')
      instances[chk]='valeur'
      b.window_create(END, window=chk)
     
    def test_2() :
      global b
      for values in b.winfo_children() :
        #print instances.keys() donne:
        #[]
        values.destroy()
     
    def test_3() :
      global b
      instances={}# initialiser après reinstanciation
      for values in restore :
        var=IntVar()
        chk=Checkbutton(b, text=values, variable=var)
        instances[chk]='valeur'
        b.window_create(END, window=chk)
     
     
     
    restore=[]
    a=Tk()
    b=Text(a)
    c=Button(a, text='Afficher', command=test_1)
    d=Button(a, text='Effacer', command=test_2)
    e=Button(a, text='Restaurer', command=test_3)
    b.pack()
    c.pack()
    d.pack()
    e.pack()
    a.mainloop()
    Sa serai sympa de m'aider si vous saissisez mon problème.

  2. #2
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    OUFFFFFF
    Je m'en suis sortie en changeant la façon d'appeller les attributs, ce qui entraine une autre question:
    Est ce que une instanciation avec le meme nom de variable, dans une autre classe avec déclaration de global de cette variable dans cette classe, entraine 2 instances ou la nouvelle instanciation remplace, normalement, l'instance précédente ?
    Explication:
    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
     
    class Test() :
     
      def test(self) :
        print 'test' 
     
    class Instance_test() :
     
      def ch_instance(self) :
        global test
        test=Test()
     
    test=Test()
    instance_test=Instance_test()
    instance_test.ch_instance()
    Merci pour vos réponses.

  3. #3
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonsoir Luke,

    Désolé mais j'ai du mal a comprendre la question.

    Tout ce que je vois c'est une mauvaise utilisation du Wrapper, soit:
    chk=Checkbutton(b, text="test", variable=var).pack()
    comme pack retourne toujours None chk = None.

    C'est normal que l'instance Variable Tk existe encore, winfo_children donne les Widgets (class Widget > class BaseWidget > class Misc)
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
        def winfo_children(self):
            """Return a list of all widgets which are children of this widget."""
            result = []
            for child in self.tk.splitlist(
                self.tk.call('winfo', 'children', self._w)):
                try:
                    # Tcl sometimes returns extra windows, e.g. for
                    # menus; those need to be skipped
                    result.append(self._nametowidget(child))
                except KeyError:
                    pass
            return result
    et l'instance Variable n'en est pas.

    Bref... Merci de donner plus d'explication svp.

    @+

  4. #4
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Re,

    Le code suivant vous montre bien que l'instance est détruite (regardez le print).
    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
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    # -*- coding: utf-8 -*-
    #
    #
    #
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
    def test_1():
        var = Tk.IntVar()
        chk = Tk.Checkbutton(b, text="test", variable=var)
        chk.pack()
        print chk.__str__()
        restore.append(chk._name)
        instances[chk._name] = chk
        b.window_create(Tk.END, window=chk)
     
    def test_2():
        for values in b.winfo_children():
            values.destroy()
     
    def test_3():
        for values in restore:
            var = Tk.IntVar()
            chk = Tk.Checkbutton(b, text=instances[values]['text'], variable=var)
            instances[chk._name] = chk
            b.window_create(Tk.END, window=chk)
     
    restore=[]
    instances={}
    a = Tk.Tk()
    b = Tk.Text(a)
    b.pack()
    Tk.Button(a, text='Afficher', command=test_1).pack()
    Tk.Button(a, text='Effacer', command=test_2).pack()
    Tk.Button(a, text='Restaurer', command=test_3).pack()
    a.mainloop()
    @++

  5. #5
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Dans l’absence de réponse je vais avancer un peut.

    Citation Envoyé par Luke spywoker Voir le message
    Est ce que une instanciation avec le meme nom de variable, dans une autre classe avec déclaration de global de cette variable dans cette classe, entraine 2 instances ou la nouvelle instanciation remplace, normalement, l'instance précédente ?
    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
     
    # -*- coding: utf-8 -*-
    #
    #
    #
    try:
        import Tkinter as Tk
    except:
        import tkinter as Tk
     
    a = Tk.Tk()
    chk = Tk.Checkbutton(a, text="test")
    chk.pack()
    chk = Tk.Checkbutton(a, text="test")
    chk.pack()
    chk = Tk.Checkbutton(a, text="test")
    chk.pack()
    print locals()
    for w in a.winfo_children():
        if isinstance(w, Tk.Checkbutton):
            print w
    Tk.Button(a, text='Quitter', command=a.quit).pack()
    a.mainloop()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    {'a': <Tkinter.Tk instance at 0xb783b7cc>, '__builtins__': <module '__builtin__' (built-in)>, '__file__': 'luke.py', 'chk': <Tkinter.Checkbutton instance at 0xb759a18c>, '__package__': None, 'Tk': <module 'Tkinter' from '/usr/lib/python2.6/lib-tk/Tkinter.pyc'>, '__name__': '__main__', '__doc__': None}
    .3078869516L
    .3078869100L
    .3076104588L
    Nous avons donc ici la création successive de trois Checkbutton.
    A chaque chk = Tk.Checkbutton(a, text="test") le wrapper demande à l'interpréteur tcl la création d'un widget, ce qui est fait. tcl crée son widget en interne.
    Comme à chaque fois nous avons chk = cela écrase le nom dans le namespace. On se retrouve donc avec une seule entrée dans le dico alors que pour tcl nous avons trois Checkbutton que vous retrouvez dans a.winfo_children().
    Le nom ne sert qu'a Python, tcl fait sa cuisine à pars.

    C'est dans le même esprit que
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    Tk.Button(a, text='Quitter', command=a.quit).pack()
    On ne nomme pas le Widget sous Phyton car nous n'en avons pas besoin : command est stocké dans le widget.

    Si vous ne retrouvez pas vos petits c'est que vous les avez perdus, pour Python, en route.
    Quelques explications possibles :
    1) Vous écrasez un nom sous Python. Exemple, vous recréez une liste au lieu de la vider. A ce propos vous devriez utiliser les méthodes des listes et dico plutôt que de les écraser comme dans votre code.
    2) Vous modifier un objet en local sans remonter l'information. Comprendre, par exemple, vous remplissez une liste dans une fonction sans toucher à celle d'origine. Vous vous retrouvez donc avec deux objets différents, l'un local et l'autre global.
    Là aussi l'utilisation des méthodes vous permet d’être sur que vous utilisez le même objet. Comprendre l.append() plutôt que
    global l
    l = []
    3) Vous avez un souci de portée. Comprendre que votre code semble comporter des noms semblables et qu'à un moment donné vous pensez utiliser un objet alors que celui ci n'est pas visible de la frame en question.
    etc...

    Dans un premier temps, et bien que cela ne soit pas très élégant, je vous proposerais d'extérioriser tout cela, dans une classe (et pas une instance de classe à chaque fois) par exemple.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    class stockage:
        restore = []
        instances = {}
    Ainsi vous accédez à vos objets via leurs méthodes. Soit stockage.restore.<méthode>. Vous êtes sur de parler de la même chose ainsi que de sa visibilité. Vous évitez aussi global, qui est trompeur en l'absence que compréhension des espaces de nom, et les effets de bord.

    @+

  6. #6
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Je précise :
    Pas d'instance de la classe
    Pas de copie locale, comprendre tutu = stockage.restore
    Utilisez les méthodes
    Répercutez le traitement local dans la classe

    @++

  7. #7
    Membre éprouvé
    Avatar de Luke spywoker
    Homme Profil pro
    Etudiant informatique autodidacte
    Inscrit en
    Juin 2010
    Messages
    1 077
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Etudiant informatique autodidacte

    Informations forums :
    Inscription : Juin 2010
    Messages : 1 077
    Par défaut
    Excuser l'absence de réponse, j'étais très occuper avec ma fonction de restauration.
    J'ai remarquer avec le besoin de restauration dans mon programme que quand je désire faire apparaitre une fenetre (Toplevel) j'utilise une méthode de classe instancier une fois puis a chaque besoin d'apparition: appel de la méthode qui contient la contruction de la fenetre que je désire faire apparaitre, donc si je ne me trompe pas, je recrées une instance a chaque appels de la methode. Je ne sais pas si c'est élégant de recréer une nouvelle instance dynamiquement, avec toutes les variables nouvellement initialiser, sauf celles du contructeur a chaque appel.

    La solution serai-t-elle de créer la fenetre dans le contructeur, afin de de pas recréer a chaque fois l'instance de la fenetre?
    Mais alors comment faire pour la faire apparaitre ?
    Je crois que je vais me mettre a dériver des classes des widgets meme si c'est périlleux pour moi.

    Ceçi dit que le programme présenter ne représente que la marche que j'ai suivis (oups pas de pack() dans mon prog) et j'ai réussi a créer la méthode de restauration en appelant autrement les variables depuis l'espace de nom global.

    Et merci pour la réponse et la précision:
    Comme à chaque fois nous avons chk = cela écrase le nom dans le namespace. On se retrouve donc avec une seule entrée dans le dico alors que pour tcl nous avons trois Checkbutton que vous retrouvez dans a.winfo_children().
    Pour régler le problème des instances Tcl il faut initialiser a.winfo_children():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a.children={}
    a.winfo_children()
    []


    Merci pour vos réponses et mes excuses pour la description confuse du problème.

  8. #8
    Membre Expert Avatar de PauseKawa
    Homme Profil pro
    Technicien Help Desk, maintenance, réseau, système et +
    Inscrit en
    Juin 2006
    Messages
    2 725
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Hérault (Languedoc Roussillon)

    Informations professionnelles :
    Activité : Technicien Help Desk, maintenance, réseau, système et +
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Juin 2006
    Messages : 2 725
    Par défaut
    Bonjour,

    Citation Envoyé par Luke spywoker Voir le message
    Pour régler le problème des instances Tcl il faut initialiser a.winfo_children():
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
     
    a.children={}
    a.winfo_children()
    []
    :
    Vous ne devriez pas touche à cela. c'est avec ce genre de code que vous perdez vos références.

    Si le Toplevel est toujours le même pourquoi ne pas utiliser les méthodes withdraw()/deiconify() ?
    Si vous devez réinitialiser des données dans le Toplevel à chaque fois que vous utilisez deiconify vous pouvez un bind sur Map
    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
    import Tkinter as Tk
     
    def callback(event):
        if event.type == '19':
            app.title('fenetre normale')
        elif event.type == '18':
            app.title('fenetre reduite')
     
    app = Tk.Tk()
    app.title('fenetre normale')
    app.geometry('300x200')
    Tk.Button(app, text='Quit', command=app.quit).pack()
    app.bind("<Unmap>", callback)
    app.after(10, lambda: app.bind("<Map>", callback))
    app.mainloop()
    @+

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Problème "No enclosing instance of the type is accessible in scope"
    Par Ludix_ dans le forum Débuter avec Java
    Réponses: 4
    Dernier message: 20/01/2014, 13h58

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