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 :

Tkinter détéction d'un clic sur la fenetre


Sujet :

Python

  1. #1
    Candidat au Club
    Homme Profil pro
    Albi
    Inscrit en
    Avril 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Albi
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 8
    Points : 4
    Points
    4
    Par défaut Tkinter détéction d'un clic sur la fenetre
    Bonjour,
    Je suis en L1 de Mathématiques, et nous devons programmer un jeu en langage python à l'aide de la bibliothèque Tkinter.
    Pour ma part, j'ai choisi de faire un jeu qui affiche une cible aléatoirement sur la fenêtre, et le but étant de cliquer dessus le plus vite possible et ainsi de suite. Mon problème est que je ne sais pas comment programmer la détection du clic de la souris sur la cible. Voila mon code provisoire :

    from Tkinter import*
    from random import*

    fen1=Tk()

    p = Canvas(fen1, width='800', height='500')

    def cercle(x, y, r, coul):
    "tracé d'un cercle de centre (x,y) et de rayon r"
    p.create_oval(x-r, y-r, x+r, y+r, fill=coul)

    def cible(taille):
    x=randrange(60,750)
    y=randrange(60,450)
    cercle(x, y, taille,'black')
    cercle(x, y, taille*3/4,'blue')
    cercle(x, y, taille*2/4,'red')
    cercle(x, y, taille*1/4, 'yellow')

    cible(50)

    p.pack()
    p.mainloop()


    En espérant avoir été claire, mais d'avance de votre réponse.

  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,

    La détection se fait avec le binding.
    Dans le cadre de l'application on utilisera widget.bind("<Button-1>", callback).
    Pour les items d'un Canvas ce sera plutôt canvas.tag_bind(item, "<Button-1>", callback)
    'callback' étant la fonction à appeler en cas d'event.
    Attention : Le bind envoie un argument de type classe event Tkinter à la fonction callback.

    @+

  3. #3
    Candidat au Club
    Homme Profil pro
    Albi
    Inscrit en
    Avril 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Albi
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Merci du conseil, j'arrive à retourner les coordonnées du clic. Par ailleurs, j'ai une autre question : Y a-t-il un moyen de trouver la couleur de la fenêtre en un point (à partir de coordonnées x et y) ?
    Parce que mon problème maintenant est de détecter si le clic est bien sur la cible, et si à partir du point je pouvais déterminer la couleur du fond, je pourrais alors déterminer si il est sur la cible ou non et distribuer des points en fonction de la précision sur la cible.
    J'avais penser à déterminer les coordonnées du clic par rapport a ceux de la cible mais comme la cible est un cercle, sa me parait plus compliqué puis que les coordonnées du x et du y de la cible varient.

  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
    Utilisez les tags pour cela : Un exemple récent du forum.

  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
    Citation Envoyé par ultimatommm Voir le message
    Par ailleurs, j'ai une autre question : Y a-t-il un moyen de trouver la couleur de la fenêtre en un point (à partir de coordonnées x et y) ?
    Vous avez, par exemple, le getpixel de PIL qui fait cela sous Windows mais vous devez passer par une image Image de PIL. Un exemple ici.
    Après cela dépend du WM : Un exemple avec win32gui ici.

    @+

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 442
    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 442
    Points : 37 034
    Points
    37 034
    Par défaut
    Salut,
    Votre cible empile des cercle de couleurs 'black', 'blue', 'red', 'yellow'.
    Après avoir exécuté canvas.bind('<Button-1>', on_click), le callback "on_click" sera appelé dès que l'utilisateur clique sur le Canvas.
    Pour savoir sur quel item, l'utilisateur à cliqué, on peut utiliser le tag spécial 'current': canvas.find_withtag('current') retourne l'item sur lequel on a cliqué ou rien du tout. A partir de là, on peut récupérer sa "couleur" avec un canvas.itemcget(item, 'fill').
    Côté code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    def on_click(event):
        items = canvas.find_withtag('current')
        if len(items):
            iid = items[0]
            print (canvas.itemcget(iid, 'fill'))
    Et juste après la création du canvas ajouter:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
        canvas.bind('<Button-1>', on_click)
    Si votre but est de faire "bouger" la cible à chaque coup, il sera plus simple de lui associer un tag: 'cible'. Ca donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    def cercle(x, y, r, coul):
    "tracé d'un cercle de centre (x,y) et de rayon r"
         canvas.create_oval(x-r, y-r, x+r, y+r, fill=coul, tag='cible')
    Ca permettra ensuite de faire bouger tous les items de la cible d'un seul coup.
    Exemple: canvas.move('cible', dx, dy)
    Bon courage,
    - W

  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
    Bonsoir wiztricks,

    En soit, et bien que la proposition des tags soit ma première réponse, je ne suis pas d'accord car les tags retournent le bbox dans le cadre d'un create_oval.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    >>> import tkinter as tk
    >>> root=tk.Tk()
    >>> c = tk.Canvas(root)
    >>> c.pack()
    >>> c.create_oval(0, 0, c.cget("width"),  c.cget("height"), fill="red")
    1
    >>> def on_click(e):
    ...     print("ok")
    ... 
    >>> c.bind('<Button-1>', on_click)
    '160814508on_click'
    Avouez que ce n'est pas très userfriendly...

    @+

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 442
    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 442
    Points : 37 034
    Points
    37 034
    Par défaut
    Salut PauseKawa,
    Vous avez certainement raison mais je ne comprends rien: le code montré en exemple n'assigne pas de tags ni de coordonnées. C'est quoi cette histoire de bbox?
    Si je reprends le code du PO:
    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
    import tkinter as tk
    from random import *
     
    def create_circle(x, y, r, color, **kwds):
        "tracé d'un cercle de centre (x,y) et de rayon r"
        canvas.create_oval(x-r, y-r, x+r, y+r, fill=color, **kwds)
     
    def create_target(size):
        x=randrange(60,750)
        y=randrange(60,450)
        create_circle(x, y, size,'black')
        create_circle(x, y, size*3/4,'blue')
        create_circle(x, y, size*2/4,'red')
        create_circle(x, y, size*1/4, 'yellow')
     
     
    def on_click(event):
        items = canvas.find_withtag('current')
        if len(items):
            iid = items[0]
            print (canvas.itemcget(iid, 'fill'))
     
    if __name__ == '__main__':
     
        app = tk.Tk()
     
        canvas = tk.Canvas(width='800', height='500')
        canvas.pack()
        create_target(50)
        canvas.bind('<Button-1>', on_click)
        tk.mainloop()
    Je n'ai pas encore besoin de "tags". Et quand on clique dans la bbox mais à l'extérieur du cercle "black", pas de 'current'.
    Qu'est ce qui vous chagrine?
    - W

  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
    Bonjour,

    Citation Envoyé par wiztricks Voir le message
    Qu'est ce qui vous chagrine?
    Le fait d'avoir proposer les tags.
    'current' est largement à son aise dans ce genre de code pour passer à coté et se tordre les méninges avec des x, y et autres tags/tag_bind.

    @+

  10. #10
    Candidat au Club
    Homme Profil pro
    Albi
    Inscrit en
    Avril 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Albi
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Merci pour tout ces conseils, j'ai pu bien avancer mon jeu.

  11. #11
    Candidat au Club
    Homme Profil pro
    Albi
    Inscrit en
    Avril 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Albi
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    Me voilà maintenant confronté a un autre problème. Je n'arrive pas à déplacer la cible à partir de la fonction on_clic
    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
    from Tkinter import*
    from random import*
     
    ########################
     
    def on_clic(event):
        items = p.find_withtag('current')
        if len(items):
            iid = items[0]
            return (p.itemcget(iid, 'fill'))
     
    def cercle(x, y, r, coul):
         p.create_oval(x-r, y-r, x+r, y+r, fill=coul, tag='cible')
     
    def cible(taille):
        x=randrange(60,750)
        y=randrange(60,450)
        cercle(x, y, taille,'black')
        cercle(x, y, taille*3/4,'blue')
        cercle(x, y, taille*2/4,'red')
        cercle(x, y, taille*1/4, 'yellow')
     
     
    ########################
    cpt=0
    fen1=Tk()
    p = Canvas(fen1, width='800', height='500')
    p.pack()
    bouton = Button(fen1, text="Quitter", command=fen1.destroy)
    bouton.pack()
     
    p.bind("<Button-1>", on_clic)
    cible(50)
     
     
     
    p.pack()
    p.mainloop()
    J'ai essayé la condition suivante sans succès :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    if on_clic=='red' or on_clic=='blue' or on_clic=='yellow' or on_clic=='black' :
         move('cible',dx,dy)
    Par ailleurs, y a-t-il un moyen de déplacer la cible par rapport au repère de la fenêtre et non au repère relatif de la cible ?

  12. #12
    Candidat au Club
    Homme Profil pro
    Albi
    Inscrit en
    Avril 2013
    Messages
    8
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Albi
    Secteur : Finance

    Informations forums :
    Inscription : Avril 2013
    Messages : 8
    Points : 4
    Points
    4
    Par défaut
    J'ai réussi à détecter si le clic est sur la cible, c'était pas très compliqué, fallait juste y penser, mais comment déplacer la cible par rapport à la fenêtre.
    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
    from Tkinter import*
    from random import*
     
    ########################
     
    def on_clic(event):
        items = p.find_withtag('current')
        if len(items):
            iid = items[0]
            if (p.itemcget(iid, 'fill'))== 'red':
                cible(50)
     
    def cercle(x, y, r, coul):
         p.create_oval(x-r, y-r, x+r, y+r, fill=coul, tag='cible')
     
    def cible(taille):
        x=randrange(60,750)
        y=randrange(60,450)
        cercle(x, y, taille,'black')
        cercle(x, y, taille*3/4,'blue')
        cercle(x, y, taille*2/4,'red')
        cercle(x, y, taille*1/4, 'yellow')
     
     
    ########################
    cpt=0
    fen1=Tk()
    p = Canvas(fen1, width='800', height='500')
    p.pack()
    bouton = Button(fen1, text="Quitter", command=fen1.destroy)
    bouton.pack()
     
    p.bind("<Button-1>", on_clic)
    cible(50)
     
     
     
    p.pack()
    p.mainloop()
    Le programme créer une nouvelle cible à chaque fois mais garde les cibles précédentes, donc il me faut soit éffacer la cible après chaque clic ou bien déplacer la cible.

  13. #13
    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
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    def on_clic(event):
        items = p.find_withtag('current')
        if len(items):
            for c in p.find_withtag('cible'):
                p.delete(c)
            cible(50)
     
    def cercle(x, y, r, coul):
         p.create_oval(x-r, y-r, x+r, y+r, fill=coul, tag='cible')
    C'est encore la solution la plus simple.

  14. #14
    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
    C'est encore la solution la plus simple.
    Pas vraiment vu que .delete() utilise le tag or id.
    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
    from Tkinter import *
    from random import *
     
     
    def on_clic(event):
        global cpt, match
        cpt += 1
        items = p.find_withtag('current')
        if items:
            match += 1
            p.delete('cible')
            cible(50)
        score.config(text="%d/%d" % (match, cpt))
     
     
    def cercle(x, y, r, coul):
         p.create_oval(x-r, y-r, x+r, y+r, fill=coul, tag='cible')
     
     
    def cible(taille):
        x = randrange(60, 750)
        y = randrange(60, 450)
        cercle(x, y, taille, 'black')
        cercle(x, y, taille*3/4, 'blue')
        cercle(x, y, taille*2/4, 'red')
        cercle(x, y, taille*1/4, 'yellow')
     
     
    cpt = 0
    match = 0
    fen1 = Tk()
    p = Canvas(fen1, width='800', height='500')
    p.pack()
    score = Label(fen1, text="0/0")
    score.pack()
    Button(fen1, text="Quitter", command=fen1.destroy).pack()
    p.bind("<Button-1>", on_clic)
    cible(50)
    fen1.mainloop()
    @+

Discussions similaires

  1. Scrollbar sur la Fenetre principale (Tkinter) ISN
    Par Displayed dans le forum Général Python
    Réponses: 1
    Dernier message: 09/09/2014, 14h22
  2. Réponses: 8
    Dernier message: 27/12/2010, 23h01
  3. ouvrire une fenetre suite a un clic sur un bouton
    Par jeune informatique dans le forum Interfaces Graphiques
    Réponses: 1
    Dernier message: 02/06/2010, 14h27
  4. Réponses: 6
    Dernier message: 13/03/2007, 11h04

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