Tkinter tortues et Threads
-
27-10-2019 - |
Question
monde! Dans les graphiques de tortues en python, il est possible de créer divers objets de tortue et les manipuler avec leurs méthodes, en avant, en arrière ... Je voulais expérimenter avec des fils j'ai donc écrit une classe filetée appelée MyTurtleManipulator.
from threading import Thread
from cTurtle import Turtle
import random
class MyTurtleManipulator(Thread):
def __init__(self, turtle):
Thread.__init__(self)
self.turtle=turtle
def run(self):
actions=[Turtle.forward, Turtle.right, Turtle.left]
while True:
action=random.choice(actions)
action(self.turtle, random.randint(1,25))
turtles=[Turtle() for i in range(5)]
threads=[MyTurtleManipulator(turtle) for turtle in turtles]
for thread in threads:
print(thread)
thread.start()
Avec l'expérience, je pensais voir toutes les tortues en mouvement « en même temps » et au hasard, mais quand je lance le programme i obtenir ces erreurs:
<MyTurtleManipulator(Thread-1, initial)>
<MyTurtleManipulator(Thread-2, initial)>
<MyTurtleManipulator(Thread-3, initial)>
<MyTurtleManipulator(Thread-4, initial)>
<MyTurtleManipulator(Thread-5, initial)>
>>> Exception in thread Thread-1:
Traceback (most recent call last):
File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
self.run()
File "/home/rfrm/test.py", line 13, in run
action(self.turtle, random.randint(1,25))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
checkargs((int, float))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
ende = self._position + self._orient * distance
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2266, in _goto
(start, self._position),
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
cl.append(-y)
File "<string>", line 1, in coords
File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop
Exception in thread Thread-2:
Traceback (most recent call last):
File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
self.run()
File "/home/rfrm/test.py", line 13, in run
action(self.turtle, random.randint(1,25))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1203, in right
checkargs((int, float))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2300, in _rotate
self._orient = self._orient.rotate(delta)
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2085, in _update
for t in screen._turtles:
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2219, in _drawturtle
screen._drawpoly(titem, shape, fill=fc, outline=oc,
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 384, in _drawpoly
cl.append(-y)
File "<string>", line 1, in coords
File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop
Exception in thread Thread-3:
Traceback (most recent call last):
File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
self.run()
File "/home/rfrm/test.py", line 13, in run
action(self.turtle, random.randint(1,25))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
checkargs((int, float))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
ende = self._position + self._orient * distance
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2270, in _goto
screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
cl.append(-y)
File "<string>", line 1, in coords
File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop
Exception in thread Thread-4:
Traceback (most recent call last):
File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
self.run()
File "/home/rfrm/test.py", line 13, in run
action(self.turtle, random.randint(1,25))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1162, in forward
checkargs((int, float))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1131, in _go
ende = self._position + self._orient * distance
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2270, in _goto
screen._drawline(self.drawingLineItem, ((0, 0), (0, 0)),
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 419, in _drawline
cl.append(-y)
File "<string>", line 1, in coords
File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop
Exception in thread Thread-5:
Traceback (most recent call last):
File "/usr/lib/python3.1/threading.py", line 516, in _bootstrap_inner
self.run()
File "/home/rfrm/test.py", line 13, in run
action(self.turtle, random.randint(1,25))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 1203, in right
checkargs((int, float))
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2300, in _rotate
self._orient = self._orient.rotate(delta)
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2085, in _update
for t in screen._turtles:
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 2219, in _drawturtle
screen._drawpoly(titem, shape, fill=fc, outline=oc,
File "/usr/local/lib/python3.1/dist-packages/cTurtle.py", line 384, in _drawpoly
cl.append(-y)
File "<string>", line 1, in coords
File "/usr/lib/python3.1/tkinter/__init__.py", line 2123, in coords
self.tk.call((self._w, 'coords') + args)))
RuntimeError: main thread is not in main loop
Qu'est-ce que cela signifie, qu'est-ce que « thread principal n'est pas en boucle principale » signifie. Nous vous remercions de votre aide.
La solution
cela semble être un python / tkinter limitation comme décrit ici , la tortue et les discussions ne sont pas amis
Autres conseils
a ses limites, mais peut-être encore possible. La réponse est dans votre messges d'erreur:
RuntimeError: fil conducteur se trouve pas dans la boucle principale
Limitez vos opérations tortue / Tkinter au fil principal. Dans mon réusinage de votre exemple ci-dessous, je l'ai utilisé le coffre-fort de fil file structure de données pour communiquer entre les fils et la tortue:
from threading import Thread, active_count
from turtle import Turtle, Screen
import queue
import random
QUEUE_SIZE = 1 # set higher the more hardware threads you have
ACTIONS = [Turtle.forward, Turtle.right, Turtle.left]
COLORS = ['red', 'black', 'blue', 'green', 'magenta']
class MyTurtleManipulator(Thread):
def __init__(self, turtle):
super().__init__()
self.turtle = turtle
def run(self):
for _ in range(100):
actions.put((self.turtle, random.choice(ACTIONS), random.randint(1, 30)))
def process_queue():
while not actions.empty():
turtle, action, argument = actions.get()
action(turtle, argument)
if active_count() > 1:
screen.ontimer(process_queue, 100)
actions = queue.Queue(QUEUE_SIZE)
for color in COLORS:
turtle = Turtle('turtle')
turtle.color(color)
turtle.setheading(random.randint(0, 360))
MyTurtleManipulator(turtle).start()
screen = Screen()
process_queue()
screen.mainloop()
Je mis la QUEUE_SIZE à 1 que je suis sur une machine avec seulement deux fils! Je suis curieux de savoir si tout fonctionne correctement sur une machine avec plus de fils et un QUEUE_SIZE ~ = #threads - 1