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 :

Commander au clavier un dessin dans un canevas


Sujet :

Tkinter Python

  1. #1
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut Commander au clavier un dessin dans un canevas
    Bonjour.
    J'essaie de déplacer une bille au clavier dans un canevas (Python 2.7):

    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
    55
    56
    57
    58
    59
    60
    61
    62
    # -*- coding: latin-1 -*-
    """
    Created on Fri Jan 16 20:22:50 2015
     
    @author: Jean-Christophe
    """
     
    # -*- coding: latin-1 -*-
    from Tkinter import *
    #Les coordonnées de la bille doivent être globales
    #pour être accessibles et modifiées dans chaque fonction deplacement
    x_bille, y_bille = 100, 100
    #Nombre de pixels à chaque décalage de la bille. Permet aussi de régler la vitesse de la bille.
    decalage_pixels = 8
    #Déplacement de la bille (permet d'aller à droite, à gauche, en haut, en bas)
    delta_x, delta_y = 0, 0 
     
     
    def calcule_delta(d_x, d_y):
        """ Fonction appelée lors de l'appui sur une flèche ou du relâchement d'une touche. 
        Elle renvoie une fonction dont le paramètre est event et qui modifie le déplacement de la bille grâce
        aux variables globales delta_x, delta_y."""
     
        def fonction_temporaire(event) :
            print event.keysym
            global delta_x, delta_y
            delta_x = d_x
            delta_y = d_y
        return fonction_temporaire
     
    def deplacement() :
        """ Fonction appelée régulièrement et qui redessine la bille à sa nouvelle position. """
     
        #On déclare les coordonnées de la bille comme globales pour les modifier.
        global x_bille, y_bille
        #On modifie les coordonnées de la bille
        x_bille += delta_x
        y_bille += delta_y
        #On redessine la bille dans le canevas
        canevas.coords(bille, x_bille, y_bille, x_bille+15, y_bille+15)
        if x_bille<800 and y_bille<600 :
            #si les coordonnées sont encore dans le canevas, on rappelle la fonction deplacement après 15 ms 
            fenetre.after(15, deplacement)
     
    #Programme principal
    fenetre = Tk()
    canevas = Canvas(fenetre, width=800, height=600, bg="white")
    canevas.pack()
    canevas.bind('<Left>', calcule_delta(-decalage_pixels, 0))
    canevas.bind('<Up>', calcule_delta(0, -decalage_pixels))
    canevas.bind('<Down>', calcule_delta(0, decalage_pixels))
    canevas.bind('<Right>', calcule_delta(decalage_pixels, 0))
    canevas.bind('<KeyRelease>', calcule_delta(0, 0))
    #On donne un nom à l'item ovale 
    bille = canevas.create_oval(x_bille, y_bille, x_bille+15, y_bille+15, fill='red')
    #On donne le focus à la fenêtre puis au canevas.
    fenetre.focus_set()
    canevas.focus_set()
     
    #On lance la fonction de déplacement
    deplacement()
    fenetre.mainloop()
    Comment éviter que la bille s'arrête quand on appuie très rapidement d'une flèche à l'autre ?
    Merci.

  2. #2
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Pourquoi "canevas.bind('<KeyRelease>', calcule_delta(0, 0))"?

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

  3. #3
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut
    Bonsoir.
    C'est pour que la bille s'arrête quand on cesse d'appuyer sur une flèche, sinon elle continue tout droit.

  4. #4
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par cal23 Voir le message
    C'est pour que la bille s'arrête quand on cesse d'appuyer sur une flèche, sinon elle continue tout droit.
    Elle continue tout droit parce que le callback "deplacement" fait avancer la balle toutes les 15ms.
    Le "canevas.bind('<KeyRelease>', calcule_delta(0, 0))" fait qu'il est nul lorsqu'on arrête d'appuyer sur la touche mais çà défait un truc dont on n'a peut être pas besoin.

    Que pensez vous de ce 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
    # -*- coding:utf-8 -*-
     
    from Tkinter import *
     
    DECALAGE_PIXELS = 8
     
    def bille_move(d_x, d_y):
     
        def fonction_temporaire(event) :
            print event.keysym
            canevas.move('bille', d_x, d_y)
        return fonction_temporaire
     
     
    #Programme principal
    fenetre = Tk()
    canevas = Canvas(fenetre, width=800, height=600, bg="white")
    canevas.pack()
    canevas.bind('<Left>', bille_move(-DECALAGE_PIXELS, 0))
    canevas.bind('<Up>', bille_move(0, -DECALAGE_PIXELS))
    canevas.bind('<Down>', bille_move(0, DECALAGE_PIXELS))
    canevas.bind('<Right>', bille_move(DECALAGE_PIXELS, 0))
    #On donne un nom à l'item ovale
     
    canevas.create_oval(100, 100, 115, 115, fill='red', tag='bille')
    canevas.focus_set()
     
    fenetre.mainloop()
    J'ai viré tout ce qui n'avait pas de rapport avec les déplacements de la "bille".

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

  5. #5
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut
    J'avais bien pensé à ce type de code mais il y a un arrêt de la bille après qu'on a appuyé sur une flèche, avant de repartir.
    C'est justement ce que je veux éviter (obtenir un déplacement exactement comme le pacman, pour les anciens ), et c'est pour ça que je suis passé par une fonction qui est appelée toutes les 15 ms, mais le problème apparaît encore.
    Il doit bien y avoir un moyen de faire un pacman piloté par des flèches: ça avance tant qu'on appuie et ça s'arrête dès qu'on relâche et sans à-coups ?

  6. #6
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Salut,

    Ah... ok. Pour moi, le pacman peut être rendu comme çà:

    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
    import Tkinter as tk
     
    DV = 5
    DELAY = 50
     
    motion_timer = None
    motion_key = None
    motion_deltas = {
        'Left': (-DV, 0),
        'Right': (DV, 0),
        'Up': (0, -DV),
        'Down': (0, DV),
        }
     
    def do_motion(canvas, dx, dy):
     
        def _doit():
            global motion_timer
     
            canvas.move('bille', dx, dy)
            motion_timer = canvas.after(DELAY, _doit)
     
        _doit()
     
    def on_key_press(event):
        global motion_timer, motion_key
     
        keysym = event.keysym
        if motion_key != keysym:
            canvas = event.widget
            if motion_timer is not None:
                canvas.after_cancel(motion_timer)
                motion_timer = None
     
            motion_key = keysym
            do_motion(canvas, *motion_deltas[keysym])
     
    if __name__ == '__main__':
     
        root = tk.Tk()
        canvas = tk.Canvas(width=600, height=600, bg='white')
        canvas.bind('<KeyPress-Left>', on_key_press)
        canvas.bind('<KeyPress-Right>', on_key_press)
        canvas.bind('<KeyPress-Up>', on_key_press)
        canvas.bind('<KeyPress-Down>', on_key_press)
     
        canvas.create_oval(100, 100, 115, 115, fill='red', tag='bille')
        canvas.pack()
        canvas.focus_set()
        tk.mainloop()
    L'idée est que bille ne change de direction que lorsqu'on appuie sur une flèche différente de la précédente.
    Lorsqu'on relâche la clé, le déplacement continue (dans la même direction).
    On ne prend en compte que les KeyPress sur les flèches et on ignore les KeyRelease.

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

  7. #7
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut
    Ca marche un peu comme ma première solution (en enlevant le keyReleased) en mieux écrit (moi j'essaie de faire simple et compréhensible pour un débutant avec Tkinter ) mais apparemment, ce n'est pas possible que la bille s'arrête quand on relâche la touche sans avoir d'à-coups à la fin .
    Tant pis
    Merci quand même.

  8. #8
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par cal23 Voir le message
    Ca marche un peu comme ma première solution (en enlevant le keyReleased) en mieux écrit (moi j'essaie de faire simple et compréhensible pour un débutant avec Tkinter ) mais apparemment, ce n'est pas possible que la bille s'arrête quand on relâche la touche sans avoir d'à-coups à la fin ..
    Dans Pacman, la bille ne s'arrête pas lorsqu'on relâche la touche mais lorsqu'on rencontre un "bord" (et dans mon code, non plus...).
    Et si la bille ne s'arrête pas quand on relâche la touche, il n'y a pas d’à-coups.

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

  9. #9
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut
    Ok, alors l'exemple du pacman n'est pas bon.
    On peut supposer que c'est un vaisseau spatial qu'on déplace avec les flèches et qui doit s'arrêter quand on relâche .

  10. #10
    Expert éminent sénior
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 283
    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 283
    Points : 36 770
    Points
    36 770
    Par défaut
    Citation Envoyé par cal23 Voir le message
    Ok, alors l'exemple du pacman n'est pas bon.
    On peut supposer que c'est un vaisseau spatial qu'on déplace avec les flèches et qui doit s'arrêter quand on relâche .
    Préciser ce qu'on veut en bon français n'est pas facile mais sans comprendre ce que vous voulez réaliser, pas la peine d'essayer de coder.

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

  11. #11
    Nouveau membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    64
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 64
    Points : 37
    Points
    37
    Par défaut
    Je pensais que quelqu'un qui a lu correctement le post aurait compris parce que j'ai quand même posé pas mal de fois la même question, mais bon...
    Bonne soirée.

Discussions similaires

  1. Réponses: 4
    Dernier message: 10/09/2006, 19h06
  2. Dessin ne s'affiche pas dans le canevas
    Par Nadjib dans le forum Langage
    Réponses: 3
    Dernier message: 24/03/2006, 21h08
  3. Dessin dans les panels d'un TStatusBar
    Par Amenofis dans le forum Composants VCL
    Réponses: 4
    Dernier message: 31/08/2004, 18h45
  4. Dessiner dans un JPanel
    Par Oliveuh dans le forum Composants
    Réponses: 5
    Dernier message: 19/07/2004, 12h13
  5. Texte dans un canevas
    Par Bernard M dans le forum Langage
    Réponses: 4
    Dernier message: 28/11/2002, 17h56

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