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 :

Actualiser valablement le texte d'un Label


Sujet :

Tkinter Python

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Août 2013
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2013
    Messages : 28
    Par défaut Actualiser valablement le texte d'un Label
    Bonjour,

    Dans le code ci-dessous , le texte du Label ne s'actualise pas correctement.
    Par contre si je mets en commentaire ( ou élimine ) les lignes 10 et 11 puis que j'active les lignes 29 et 30 tout rentre dans l'ordre.
    Cela a certainement rapport avec les espaces de noms mais je n'arrive pas à comprendre la cause.

    Merci à ceux d'entre vous qui maîtrisent le sujet de m'éclairer.

    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
    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    from tkinter import *
     
     
    def changer():
     
        global c
     
        truc=Label(fen, bg="lightblue", font="Arial 14")
        truc.place(relx=0.2, rely = 0.2)
     
     
        if c =="Un très long message":
            c="Court message"
        else:
            c="Un très long message"
     
        truc.configure(text=c)
     
    #####
     
    fen=Tk()
    fen.geometry("400x250")
    fen.config(bg="bisque")
     
    c="Court message"
     
    #truc=Label(fen, bg="lightblue", font="Arial 14",text=c)
    #truc.place(relx=0.2, rely = 0.2)
     
    machin=Button(fen,text="Changer le message",command=changer, bg="lightgreen")
    machin.place(relx=0.2, rely = 0.6)
     
    fen.mainloop()

  2. #2
    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,

    A la ligne 29 vous créez un Widget Label Tcl/Tk que vous nommez truc pour Python.
    Ce Widget est, accessoirement, positionné par le gestionnaire de géométrie place à la ligne 30.
    Ligne 10 vous créez un autre Widget, que vous nommez aussi truc, que vous positionnez au même endroit avec place. Vous 'écrasez' graphiquement le Label.
    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
    from tkinter import *
     
     
    def changer():
     
        global c
     
        truc=Label(fen, bg="lightblue", font="Arial 14")
        print(id(truc))
        truc.place(relx=0.2, rely = 0.2)
     
     
        if c =="Un très long message":
            c="Court message"
        else:
            c="Un très long message"
     
        truc.configure(text=c)
     
    #####
     
    fen=Tk()
    fen.geometry("400x250")
    fen.config(bg="bisque")
     
    c="Court message"
     
    truc=Label(fen, bg="lightblue", font="Arial 14",text=c)
    truc.place(relx=0.2, rely = 0.2)
    print(id(truc))
     
    machin=Button(fen,text="Changer le message",command=changer, bg="lightgreen")
    machin.place(relx=0.2, rely = 0.6)
     
    fen.mainloop()
    C'est deux objets différents.
    Sortie :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    139889483347216
    139889477556560
    Maintenant le premier nom truc est présent dans l'espace de nom global de la fonction changer et vous pouvez donc utiliser son option .configure()
    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
    from tkinter import *
     
     
    def changer():
     
        global c
     
        print(globals()['truc'])
     
     
        if c =="Un très long message":
            c="Court message"
        else:
            c="Un très long message"
     
        truc.configure(text=c)
     
    #####
     
    fen=Tk()
    fen.geometry("400x250")
    fen.config(bg="bisque")
     
    c="Court message"
     
    truc=Label(fen, bg="lightblue", font="Arial 14",text=c)
    truc.place(relx=0.2, rely = 0.2)
     
    machin=Button(fen,text="Changer le message",command=changer, bg="lightgreen")
    machin.place(relx=0.2, rely = 0.6)
     
    fen.mainloop()
    Sortie :
    En fait puisque "truc" est défini dans le main il est accessible pour tous.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def changer():
        def warp():
            print("c in warp ?", "c" in globals())
        warp()
        print("c in changer ?", "c" in globals())
     
    c = "Un texte"
    changer()
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    c in warp ? True
    c in changer ? True
    @+

  3. #3
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Août 2013
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2013
    Messages : 28
    Par défaut
    PauseKawa,

    Merci de votre réponse que je vais étudier.

    En fait je ne crée pas deux fois truc car les lignes 29 et 30 sont mises en commentaire; C'est comme si elles n'existaient pas. Dans cette configuration le programme cafouille.

    Par contre si j'élimine la déclaration de truc en lignes 9 et 10 et que je l'active en lignes 29 et 30 tout va bien.

    Je ne m'étais pas exprimé assez clairement.

    Dans vos suggestions il y a des pistes et outils que je vais étudier. merci.

  4. #4
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Août 2013
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2013
    Messages : 28
    Par défaut
    J'ai lu un peu trop vite votre réponse.

    Si je comprends bien, dans la configuration qui ne fonctionne pas, à chaque fois qu'on fait appel à change, c'est un nouveau widget truc qui est créé, l'adresse mémoire qui définissait l'ancien truc n'existe plus par contre le widget est resté présent sur la fenêtre. Il aurait fallu l'afficher quelques secondes, puis l'effacer de la fenêtre avant de quitter la fonction change afin qu'il disparaisse de la fenêtre.

    Ceci dit, c'est juste pour m'assurer que j'ai bien compris, la façon raisonnable de procéder est comme vous le dites de rendre truc présent dans l'espace de nom global de la fonction change

    Encore merci.

  5. #5
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 741
    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 741
    Par défaut
    Citation Envoyé par couragecourage Voir le message
    Si je comprends bien, dans la configuration qui ne fonctionne pas, à chaque fois qu'on fait appel à change, c'est un nouveau widget truc qui est créé, l'adresse mémoire qui définissait l'ancien truc n'existe plus par contre le widget est resté présent sur la fenêtre.
    Parler d'"adresse mémoire" est une représentation de ce qu'il se passe qui vous foutra dedans tant que vous n'arriverez pas a vous en débarrasser.
    Essayons de partir d'un truc "simple":
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> a = 1
    >>> def foo():
    ...      a = 2
    ...
    Vous avez "appris" que l'appel a "foo" ne changera pas le "a" dit global. Le "a" de "foo" sera, par défaut, local.
    Et cette représentation suffit pour avancer un peu.

    Compliquons un peu:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    >>> a = tk.Label(...)
    >>> def foo():
    ...      a = tk.Label(...)
    ...
    C'est la même structure, nous avons seulement changé d'objet... et la représentation local/global/adresse mémoire ne fonctionne plus.

    Pourquoi?
    Essentiellement parce qu'objets et "variables" n'ont plus la même durée de vie.

    Avec "a = 2", on associe "a" - local - a l'objet int('2').
    A la sortie de la fonction, l'espace local est détruit.
    Le "a", seule référence a l'objet crée pendant la fonction, étant supprimée, le nombre de références a l'objet devient 0
    => l'objet est inaccessible et la "garbage collection" pourra le détruire quand il veut.

    tk.Label est une race d'objet qui ne sera détruite qu’après l'appel explicite de la méthode .destroy.
    Techniquement, tkinter stocke une référence a l'objet dans le parent (ici "fen"). A la sortie de la fonction, "a" est toujours détruit mais le nombre de référence a l'objet ne sera plus 0 => un nouvel objet sera crée a chaque appel.

    Juste pour le "fun", je me suis amuse a modifier votre programme pour montrer un accès par nom du widget ou via emballage dans le paramètre d'appel d'une fonction.

    tkinter est très bien pour apprendre la différence entre le monde des objets et des chemins qui permettent d'y accéder (dans lesquels sont ce qu'on appelle "variable").


    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
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    import tkinter as tk
     
    messages = [
        'long message',
        'court message',
        ]
     
    app=tk.Tk()
    app.geometry("400x250")
    app.config(bg="bisque")
     
    ix = 0
    m = messages[ix]
     
    tk.Label(bg="lightblue", font="Arial 14",text=m, name='label').pack()
    app.title('label par nom')
    ### passage du label par nom (simple).
    def changer():
        global ix
        label = app.children.get('label')
        ix = (ix + 1) % len(messages)
        label.configure(text=messages[ix])
     
    btn = tk.Button(text="Changer le message",
                 command=changer,
                 bg="lightgreen")
    btn.pack()
     
    tk.Button(app, text="next", command=app.quit).pack()
     
    app.mainloop()
     
    ### passage du label via les parametres par defaut d'une
    ### fonction.
    app.title('label via lambda')
    def changer(label):
        global ix
     
        ix = (ix + 1) % len(messages)
        label.configure(text=messages[ix])
     
    label = app.children.get('label')
    btn['command'] = lambda label=label: changer(label)
    app.mainloop()
     
    app.title('label via globals()')
    def changer():
        global ix
     
        ix = (ix + 1) % len(messages)
        label.configure(text=messages[ix])
     
    btn['command'] = changer
    app.mainloop()
    - W

    PS: mais ca ne fait que radoter sur ce qu'a deja dit PauseKawa
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  6. #6
    Membre averti
    Homme Profil pro
    retraité
    Inscrit en
    Août 2013
    Messages
    28
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : retraité
    Secteur : Enseignement

    Informations forums :
    Inscription : Août 2013
    Messages : 28
    Par défaut
    Merci beaucoup à vous deux pour ces réponses éclairantes.

    Peu à peu ces notions deviennent plus claires et certaines notions expliquées dans les wikibooks et autres tutoriels et forums deviennent plus tangibles.

    Je marque ce sujet comme résolu.

  7. #7
    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
    J'avais bien compris et c'est sans doute mon explication qui n'est pas nette.

    Lorsque vous assignez 'truc' sous Python en lui disant que c'est un objet Tcl/Tk vous créez un Widget Tcl/Tk.
    Si vous ré assignez 'truc' sous Python l'objet Tcl/Tk précédent existe encore pour pour l'interpréteur Tcl/Tk car vous ne l'avis pas détruit pour celui-ci, vous avez juste écraser sa référence sous Python. Et, accessoirement, comme vous l'avez positionner avec place, vous l'avez à l'écran.
    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
    from tkinter import *
     
     
    def changer():
     
        global c, truc
        if c =="Un très long message":
            c="Court message"
        else:
            c="Un très long message"
        truc.destroy()  # <<<<<<<<<<
        truc = Label(fen, bg="lightblue", font="Arial 14", text=c)
        truc.place(relx=0.2, rely=0.2)
        print(id(truc))
     
     
    c = "Court message"
     
     
    fen = Tk()
    print(dir(fen))
    fen.geometry("400x250")
    fen.config(bg="bisque")
    truc = Label(fen, bg="lightblue", font="Arial 14", text=c)
    truc.place(relx=0.2, rely=0.2)
    print(id(truc))
    machin = Button(fen, text="Changer le message", command=changer, bg="lightgreen")
    machin.place(relx=0.2, rely=0.6)
    fen.mainloop()
    D’où votre 'bug' (qui n'en est pas un) graphique.

    Utiliser l'option .configure() permet de 'réutiliser' le Widget sans le détruire (.destroy()).

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

Discussions similaires

  1. [MFC]Impossible de changer le texte d'un LABEL
    Par jlassira dans le forum MFC
    Réponses: 7
    Dernier message: 01/03/2006, 16h39
  2. Actualiser <input type"text" d'après <select
    Par Scratchy dans le forum Général JavaScript
    Réponses: 4
    Dernier message: 21/02/2006, 15h01
  3. [Rave5] Comment envoyer un text ver un label
    Par pacs dans le forum Rave
    Réponses: 2
    Dernier message: 03/03/2005, 14h55
  4. [Flash MX] Actualisation scroll sur texte dynamique
    Par Gothico dans le forum Flash
    Réponses: 2
    Dernier message: 23/09/2004, 14h42
  5. Faire defiler Texte dans un label
    Par Techsan dans le forum Composants VCL
    Réponses: 5
    Dernier message: 08/06/2003, 23h29

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