Récemment, j'ai remarqué qu'on était facilement bloqué avec Tkinter lorsqu'on voulait faire un jeu qui nécessite l'appui simultané sur différentes touches du clavier.
Je me suis donc mis dans l'optique de créer un widget qui faciliterait l'accès à l'utilisateur de TOUTES les touches appuyées.
L'idée est simple:
on a un set qui contient les touches
à chaque appui, on ajoute la touche au set
à chaque relâchement, on la retire
Si l'utilisateur veut connaitre les touches, on lui renvoie le set
J'en suis arrivé au code suivant:
# -*- encoding:utf-8 -*-
# using Python 3.4.4
import tkinter as tk
class Tk_Multikey(tk.Frame):
"""Allow the user to get all actived keys"""
def __init__(self, master, **kwargs):
super().__init__(master, **kwargs)
self.keysym = set()
self.keycode = set()
self.keysym_num = set()
master.bind('<KeyPress>', self.add_a_key, add='+')
master.bind('<KeyRelease>', self.discard_a_key, add='+')
def add_a_key(self, event):
"""When a key is pressed, add its keysym, keycode and keysym_num to the
corresponding set"""
self.keysym.add(event.keysym.upper()) # the upper method prevents a
# bug when the user is using the Shift/Caplock key and a letter key
self.keycode.add(event.keycode)
self.keysym_num.add(event.keysym_num)
def discard_a_key(self, event):
"""When a key is released, discard its keysym, keycode and keysym_num to
the corresponding set"""
self.keysym.discard(event.keysym.upper())
self.keycode.discard(event.keycode)
self.keysym_num.discard(event.keysym_num)
def __delattr__(self, nameattr):
"""The user is not allowed to delete a set"""
raise AttributeError("Unable to delete")
def get_keys(self):
return((self.keysym, self.keycode, self.keysym_num))
if __name__ == "__main__":
def update(event=None):
print("updating")
strvar_keysym.set(mtk.keysym)
strvar_keycode.set(mtk.keycode)
strvar_keysym_num.set(mtk.keysym_num)
root = tk.Tk()
mtk = Tk_Multikey(root)
mtk.pack()
root.bind('<KeyPress>', update, add='+')
root.bind('<KeyRelease>', update, add='+')
strvar_keysym = tk.StringVar()
strvar_keycode = tk.StringVar()
strvar_keysym_num = tk.StringVar()
update()
tk.Label(root, textvariable=strvar_keysym).pack()
tk.Label(root, textvariable=strvar_keycode).pack()
tk.Label(root, textvariable=strvar_keysym_num).pack()
root.mainloop()
Ce code semble entièrement fonctionnel, cependant je suis déconcerté face au problème suivant:
Lorsqu'on appuie sur A, puis Z, puis E, puis R; ca affiche les 4. Mais si on rajoute le T, ca ne marche plus. Pourtant, si on retire le R, et qu'on rééssaie le T, ca marche.
J'ai tiré la conclusion (trop hâtive) que le nombre maximal ne pouvait excéder 4 touches, ce qui me semblait absurde.
J'ai ensuite testé avec d'autre touches du clavier, et certaines passent, d'autre non.
On a le même problème avec W, X, C (le C ne passe pas..)
Seriez-vous m'indiquer d'où provient ce bug? (ou alors si n'arrive qu'avec mon Pc; j'ai pas testé sur une autre machine) Si oui, auriez-vous une solution à me proposer?
Merci d'avance, et bonne soirée à tous.
Si je suis tête en l'air, c'est par habitude de viser le sommet
Quand tu restes appuyé sur une touche, en fait il y a une succession de keypress et keyrelease qui sont exécutés (rajoute un print dans chaque méthode pour t'en rendre compte). Ce comportement s'appelle le bouncing (trad: le rebond) et c'est peut-être ce qui créé des problèmes dans ton programme.
Il y a un code sur github qui permet de retirer le rebond (debouncing), regarde si ça peut t'aider (j'avoue ne pas mettre plonger dans son code donc je ne sais comment il s'y prend ni même si ça pourra t'aider)
J'ai testé ton code, et pour moi le max est de 6 touches simultanément. Je me demande si ce n'est pas une restriction de l'os (et non de tkinter). Peut-être existe-il une commande (avec le module os) pour outrepasser cette restriction. J'ai un peu cherché sur SO, mais je n'ai rien trouvé (peut-être que poser cette question sur SO pourrait être intéressant).
EDIT: J'ai testé le code de github mais je comprend pas vraiment ce qu'il apporte en rapport avec le debouncing.. Le code laisse quand même tous les evenements passer et donc ne ralentit pas la charge...
Sinon j'ai réussi à monter à 8-9 touches avec mon code en testant différentes combinaisons.
- Edité par WexyR 21 octobre 2016 à 15:26:30
Si je suis tête en l'air, c'est par habitude de viser le sommet
C'est parce que j'avais prévu de le faire que je me suis retrouvé fasse à ce problème C'était néanmoins intéressant de tomber sur ce problème dont je m'attendais pas du tout Maintenant les gens pourront utiliser mon programme pour tester si leur clavier est de bonne qualité ou pas haha..
J'avoue que j'ai été plutôt surpris quand il m'a parlé d'une limitation mécanique.. J'ai été déçu de mon ordi
Si je suis tête en l'air, c'est par habitude de viser le sommet
[Tkinter] Bind plusieurs touches
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.