Tkinter海龟和线程

时间:2011-05-01 06:20:21

标签: python tkinter python-multithreading turtle-graphics

世界!在python中的turtle图形中,可以创建各种Turtle对象并使用它们的方法操作它们,向前,向后......我想尝试线程,所以我编写了一个名为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()

通过实验我希望看到所有的海龟“同时”和随机地移动但是当我运行程序时我得到了这些错误:

<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

这意味着什么,“主线程不在主循环中”是什么意思。谢谢你的帮助。

2 个答案:

答案 0 :(得分:1)

这似乎是一个python / tkinter限制as described here,龟和线程不是朋友

答案 1 :(得分:0)

这有其局限性,但仍有可能。答案就在你的错误中:

  

RuntimeError:主线程不在主循环中

将turtle / tkinter操作限制为主线程。在我对下面的示例进行的修改中,我使用了线程安全的队列数据结构来在线程和乌龟之间进行通信:

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()

我在一台只有两个线程的机器上将QUEUE_SIZE设置为1!我很想知道在一个有更多线程的机器上是否一切正常并且QUEUE_SIZE~ = #threads - 1

enter image description here