Tkinter 海龟和线程

发布于 2024-11-04 11:39:56 字数 5876 浏览 0 评论 0原文

世界!在 python 中的海龟图形中,可以创建各种 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

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

world! In turtle graphics in python, there's possible to create various Turtle objects and manipulate them with their methods, forward, backward... I wanted to experiment with threads so I wrote a threaded class called 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()

With the experiment I expected to see all the turtles moving "simultaneously" and randomly but When I run the program i get these errors:

<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

What does this means, what does "main thread is not in main loop" means. Thank you for your help.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

来世叙缘 2024-11-11 11:39:56

这似乎是 python/tkinter 的限制如此处所述,海龟和线程不是朋友

this seems to be a python/tkinter limitation as described here, turtle and threads are not friends

命比纸薄 2024-11-11 11:39:56

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

运行时错误:主线程不在主循环中

中将您的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

在此处输入图像描述

This has its limitations but may still be possible. The answer is in your error messges:

RuntimeError: main thread is not in main loop

Limit your turtle/tkinter operations to the main thread. In my rework of your example below, I've used the thread safe queue data structure to communicate between the threads and turtle:

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

I set the QUEUE_SIZE to 1 as I'm on a machine with only two threads! I'm curious to know if everything works correctly on a machine with more threads and a QUEUE_SIZE ~= #threads - 1

enter image description here

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文