Mon petit frère se lance juste dans la programmation et pour son projet d'expo-sciences, il fait une simulation d'une volée d'oiseaux dans le ciel. Il a écrit la majeure partie de son code, et cela fonctionne bien, mais les oiseaux doivent bouger à chaque instant .
Tkinter, cependant, monopolise le temps de sa propre boucle d'événements, et donc son code ne s'exécutera pas. Faire root.mainloop()
s'exécute, s'exécute et continue de s'exécuter, et la seule chose qu'il exécute est les gestionnaires d'événements.
Existe-t-il un moyen de faire fonctionner son code le long de la boucle principale (sans multithreading, c'est déroutant et cela devrait rester simple), et si oui, qu'est-ce que c'est?
En ce moment, il a inventé un horrible hack, liant sa move()
fonction à <b1-motion>
, de sorte que tant qu'il maintient le bouton enfoncé et agite la souris, cela fonctionne. Mais il doit y avoir un meilleur moyen.
threading
module.La solution publiée par Bjorn aboutit à un message "RuntimeError: Calling Tcl from different appartment" sur mon ordinateur (RedHat Enterprise 5, python 2.6.1). Bjorn n'a peut-être pas reçu ce message, car, selon un endroit que j'ai vérifié , une mauvaise gestion des threads avec Tkinter est imprévisible et dépend de la plate-forme.
Le problème semble être que cela
app.start()
compte comme une référence à Tk, car l'application contient des éléments Tk. J'ai corrigé cela en le remplaçantapp.start()
par unself.start()
intérieur__init__
. J'ai également fait en sorte que toutes les références Tk soient soit à l'intérieur de la fonction qui appelle,mainloop()
soit à l'intérieur des fonctions appelées par la fonction qui appellemainloop()
(ceci est apparemment critique pour éviter l'erreur "différent appartement").Enfin, j'ai ajouté un gestionnaire de protocole avec un rappel, car sans cela, le programme se termine avec une erreur lorsque la fenêtre Tk est fermée par l'utilisateur.
Le code révisé est le suivant:
la source
run
méthode? Je n'arrive pas à comprendre comment ...__init__(..)
, les stockiezself
et lesrun(..)
while app.is_alive(): etc
Lorsque vous écrivez votre propre boucle, comme dans la simulation (je suppose), vous devez appeler la
update
fonction qui fait ce quemainloop
fait: met à jour la fenêtre avec vos modifications, mais vous le faites dans votre boucle.la source
task
l'appel, vous vous retrouverez avec des boucles d'événements imbriquées, et c'est mauvais. À moins que vous ne compreniez parfaitement le fonctionnement des boucles d'événements, vous devez éviter d'appelerupdate
à tout prix.Une autre option est de laisser tkinter s'exécuter sur un thread séparé. Une façon de le faire est comme ceci:
Attention cependant, la programmation multithread est difficile et il est vraiment facile de se tirer une balle dans le pied. Par exemple, vous devez être prudent lorsque vous modifiez les variables membres de la classe exemple ci-dessus afin de ne pas interrompre avec la boucle d'événements de Tkinter.
la source
Il s'agit de la première version fonctionnelle de ce qui sera un lecteur GPS et un présentateur de données. tkinter est une chose très fragile avec beaucoup trop peu de messages d'erreur. Il ne met rien en place et ne dit pas pourquoi la plupart du temps. Très difficile venant d'un bon développeur de formulaires WYSIWYG. Quoi qu'il en soit, cela exécute une petite routine 10 fois par seconde et présente les informations sur un formulaire. Il a fallu un certain temps pour y arriver. Lorsque j'ai essayé une valeur de minuterie de 0, le formulaire ne s'est jamais présenté. Ma tête me fait mal maintenant! 10 fois ou plus par seconde, c'est assez bien pour moi. J'espère que cela aide quelqu'un d'autre. Mike Morrow
la source