2011-05-01 80 views
1

世界!在python的turtle圖形中,可以創建各種Turtle對象並使用它們的方法來操縱它們,向前,向後...我想試驗線程,所以我寫了一個名爲MyTurtleManipulator的線程類。Tkinter海龜和線程

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 

這是什麼意思,什麼是「主線程不在主循環中「的意思。感謝您的幫助。

回答

1

這似乎是一個Python/Tkinter的限制as described here,龜和線程不是朋友

+0

哦,這是可悲的...您的幫助謝謝 – rfrm 2011-05-01 06:44:05

0

這有它的侷限性,但仍然有可能。答案出現在你的錯誤信息中:

RuntimeError: main thread is not in main loop

將你的龜/ 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