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

Python Discussion :

[python3+tkinter]demande d'aide sur un programme.


Sujet :

Python

  1. #1
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 27
    Points : 20
    Points
    20
    Par défaut [python3+tkinter]demande d'aide sur un programme.
    bonjour à tous et à toutes.
    voila je cherche à faire un programme me permettant de "switcher" d'un élément vers un autre et vice versa.
    voila mon code:

    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
    from tkinter import *
     
    ##fonctions
    def drwcircle1(event):
        ""
        can.create_oval(event.x-10,event.y-10,event.x+10,event.y+10,outline="dark red",width=2)
     
    def drwcircle2(event):
        ""
        can.create_oval(event.x-20,event.y-20,event.x+20,event.y+20,outline="green",width=2)
     
    def swtccirc():
        global a
        if a == drwcircle1:
            a = drwcircle2
        elif a == drwcircle2:
            a = drwcircle1
     
     
    #program
    a = drwcircle2
     
    #interface
    fen = Tk()
    can = Canvas(fen,width=200, height=200, bg="white")
    can.bind("<Button-1>",a)
    can.pack()
    Button(fen,text="change circle",command=swtccirc).pack()
     
    fen.mainloop()
    bien entendu celui ci ne fonctionne pas (ca serait tellement plus simple). alors j'ai tenté de faire un autre code (à peu près sur le même principe)
    le voici:
    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
    from tkinter import *
     
    #fonctions
    def drwcircle():
        #canv.create_oval(50,50,150,150,outline="red")
        canv.create_oval(50,50,150,150,outline=coul)
     
    def chngcoul():
        global coul
        if coul == "red":
            coul = "green"
        elif coul == "green":
            coul = "red"
     
    #programme
    coul="red"
     
    #grahpique
    fen = Tk()
    canv = Canvas(fen,width=200,height=200,bg="white")
    canv.pack()
    Button(fen,text="change color",command=chngcoul).pack(side=BOTTOM)
    Button(fen,text="drwcircle",command=drwcircle).pack()
     
    fen.mainloop()
    donc dans celui-ci la couleur change bien. dans le 1er je désire que le cercle change.

    merci pour vos explications et votre aide.

    cdt

  2. #2
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonjour,

    Pour ce qui est du premier code le Button fait que la variable 'a' contient une des deux fonctions.
    A partir de là il est nécessaire pour qu'il 'se passe quelque chose' à un moment donné d’exécuter la fonction.
    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
    from tkinter import *
     
    ##fonctions
    def drwcircle1(event):
        ""
        can.create_oval(event.x-10,event.y-10,event.x+10,event.y+10,outline="dark red",width=2)
     
    def drwcircle2(event):
        ""
        can.create_oval(event.x-20,event.y-20,event.x+20,event.y+20,outline="green",width=2)
     
    def swtccirc():
        global a
        if a == drwcircle1:
            a = drwcircle2
        elif a == drwcircle2:
            a = drwcircle1
     
     
    #program
    a = drwcircle2
     
    #interface
    fen = Tk()
    can = Canvas(fen,width=200, height=200, bg="white")
    # can.bind("<Button-1>",a) Voir plus bas
    can.pack()
    Button(fen,text="change circle",command=swtccirc).pack()
    can.bind("<1>", lambda event: a(event))
     
    fen.mainloop()
    Vous remarquerez le lambda event: a(event) permettant de récupérer l'objet event envoyé par le binding. Donc a voir : bind et lambda.

    Si j'ai bien compris.

    @+
    Merci d'utiliser le forum pour les questions techniques.

  3. #3
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 27
    Points : 20
    Points
    20
    Par défaut
    bonjour
    effectivement la modification effectue bien ce que je veux.
    je vais étudier ta solution merci.

  4. #4
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Bonne lecture dans ce cas.

    Notez que drwcircle1 et drwcircle2 sont les mêmes fonctions dont seulement deux valeurs changes (10/20, couleur).
    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
    from tkinter import *
     
     
    SIZE = 10
    COLOR = 'green'
     
     
    def drwcircle(event):
        ""
        can.create_oval(event.x-SIZE,
                        event.y-SIZE,
                        event.x+SIZE,
                        event.y+SIZE,
                        outline=COLOR,
                        width=2)
     
     
    def swtccirc():
        global COLOR, SIZE
        if COLOR == 'green':
            COLOR = 'dark red'
            SIZE = 20
        else:
            COLOR = 'green'
            SIZE = 10
     
     
    fen = Tk()
    can = Canvas(fen,width=200, height=200, bg="white")
    can.pack()
    Button(fen, text="change circle", command=swtccirc).pack()
    can.bind("<1>", drwcircle)
    fen.mainloop()
    "yapuqua"

    @+
    Merci d'utiliser le forum pour les questions techniques.

  5. #5
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Juste au passage :

    Pourquoi dans votre premier code cela ne fonctionne pas ?

    Si nous prenons
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    a = drwcircle2
    ...
    can.bind("<Button-1>", a)
    Lors de la lecture du code le binding est effectué sur a, soit dans le code drwcircle2, et c'est cette fonction qui est stockée comme callback.

    Si par contre vous écrivez
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    can.bind("<Button-1>", lambda event: a(event))
    La fonction stockée est la fonction lambda et lors de son exécution elle appelle la fonction 'a', qui correspond à drwcircle2 ou 1 au moment 't'.

    Sans les fonctions lambda cela donne:
    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
    from tkinter import *
     
    ##fonctions
    def drwcircle1(event):
        ""
        can.create_oval(event.x-10,event.y-10,event.x+10,event.y+10,outline="dark red",width=2)
     
    def drwcircle2(event):
        ""
        can.create_oval(event.x-20,event.y-20,event.x+20,event.y+20,outline="green",width=2)
     
    def swtccirc():
        global a
        if a == drwcircle1:
            a = drwcircle2
        elif a == drwcircle2:
            a = drwcircle1
     
     
    def lmbd(event):
        a(event)
     
     
    #program
    a = drwcircle2
     
    #interface
    fen = Tk()
    can = Canvas(fen,width=200, height=200, bg="white")
    can.bind("<Button-1>", lmbd)
    can.pack()
    Button(fen,text="change circle",command=swtccirc).pack()
     
    fen.mainloop()
    Merci d'utiliser le forum pour les questions techniques.

  6. #6
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 27
    Points : 20
    Points
    20
    Par défaut
    ah merci beaucoup je me demandais aussi comment le faire sans passer par la fonction lambda.
    merci

  7. #7
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    Citation Envoyé par PauseKawa Voir le message
    Lors de la lecture du code le binding est effectué sur a
    Une petite explication sur ceci qui pourrais être mal interprété.

    Un petit rappel rapide:
    Python ne gère pas le Windows Manager en natif, pour cela il utilise des GUI.
    Tkinter est un (le) wrapper Python de Tcl/Tk. C'est une bibliothèque Python donnant accès a l'interpréteur Tcl et principalement à son toolkit graphique : Tk.
    Nous avons donc
    Python <-> Tkinter <-> Tcl/Tk
    Tkinter permettant de créer l'interface Tk et l'interpréteur Tcl gérant le WM via Tk (événements etc...).
    Pour ce qui est des 'événements' Tkinter dispose d'une palette de fonctions (bind, protocol, command...) permettant de remonter l'information ('réagir' via des fonctions) à l'interpréteur Python.

    Le binding permet d'enregistrer une action (fonction) pour un événement du WM. Je passerais sur les détails des _register et autre mais cela demande à l'interpréteur Tcl d’effectuer une action lorsque le toolkit Tk remonte en événement donné (clic etc...) pour un élément donné.
    A notre niveau cela se traduit par l’exécution d'une fonction lors d'un événement pour un objet graphique donné.

    Au niveau du code nous avons donc:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    can.bind("<Button-1>", a)
    Qui se traduit par
    Pour un clic ("<Button-1>") sur le Canvas can exécuter 'a'.
    Mais comme a = drwcircle2 la fonction enregistrée au moment du binding pour l'action "<Button-1>" est drwcircle2.
    Puisque la fonction n'est pas 'enregistrée au niveau' de Python qu'importe si par la suite 'a' est autre chose pour Python.
    Lorsque nous avons can.bind("<Button-1>", lmbd) c'est la fonction lmbd qui est prise en compte et comme celle ci a pour code
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    def lmbd(event):
        a(event)
    Elle exécuteras la fonction ayant pour nom 'a' telle qu'elle est à l'instant 't' pour Python.
    Lambda n'est là que pour éviter de créer une fonction lmbd n'ayant pour but que de faire un a(event).

    Voili : Grossier et a revoir sans doute mais cela dégrossi le sujet.
    Merci d'utiliser le forum pour les questions techniques.

  8. #8
    Membre à l'essai
    Profil pro
    Inscrit en
    Juin 2011
    Messages
    27
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Juin 2011
    Messages : 27
    Points : 20
    Points
    20
    Par défaut
    bonjour
    merci pour ce complément. j'ai compris mon erreur à la lumière de ces informations. merci pour ces explications!

  9. #9
    Expert confirmé 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
    Points : 4 005
    Points
    4 005
    Par défaut
    A noter que l'explication est valable pour le trace_variable de la classe Variable, selection_handle, wm_protocol, le dump du Widget Text ou encore le validatecommand du Widget Entry : De quoi avoir un beau bug
    after n'est pas concerné car le _register est fait sur la fonction interne callit.

    (Edit : Avec un exemple)
    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
    import Tkinter as tk
     
     
    def foo1():
        print('in foo1')
        return True
     
     
    def foo2():
        print('in foo2')
        return True
     
     
    def toprint():
        a()
     
     
    def change():
        print('change for foo2')
        global a
        a = foo2
     
     
    app = tk.Tk()
    a = foo1
    tk.Entry(app, validate='key', validatecommand=a).pack()
    tk.Button(app, text='change for foo2', command=change).pack()
    tk.Button(app, text='give me a', command=toprint).pack()
    tk.Button(app, text='call a', command=a).pack()
    app.mainloop()
    @+
    Merci d'utiliser le forum pour les questions techniques.

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

Discussions similaires

  1. Aide sur un programme Client Serveur
    Par clubmed01 dans le forum Linux
    Réponses: 33
    Dernier message: 29/05/2012, 10h22
  2. Demande d'aide sur "programmation d'un IDS en Java"
    Par Libre_ar2009 dans le forum Général Java
    Réponses: 0
    Dernier message: 04/05/2009, 16h08
  3. [VB6] Demande d'aide sur un programme !
    Par Lucas42 dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 16/06/2006, 11h49
  4. demande d'aide sur samba
    Par marcoss dans le forum Développement
    Réponses: 5
    Dernier message: 04/12/2003, 19h38

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