在像 turtle 这样的事件驱动的世界中,你不应该这样做:
counter = 1
...
while counter==1:
这有可能锁定事件。此外,没有办法彻底退出该程序。不是在循环中移动不同的距离while
,而是移动一个恒定的距离,但在一个事件中具有不同的延迟ontimer()
(应该与 Python 2 或 3 一起使用):
from turtle import Turtle, Screen
RADIUS = 250
ISS_DELAY = 100 # milliseconds
ROCKET_DELAY = 75 # milliseconds
CURSOR_SIZE = 20
def move_ISS():
ISS.circle(RADIUS, 1)
screen.ontimer(move_ISS, ISS_DELAY)
def move_rocket():
rocket.circle(RADIUS, 1)
# rocket slows to ISS' speed once docked
delay = ISS_DELAY if rocket.distance(ISS) <= CURSOR_SIZE else ROCKET_DELAY
screen.ontimer(move_rocket, delay)
screen = Screen()
screen.title("ISS")
screen.setup(750, 750)
ISS = Turtle("square", visible=False)
ISS.speed('fastest')
ISS.penup()
ISS.left(180)
ISS.sety(RADIUS)
ISS.showturtle()
ISS.pendown()
rocket = Turtle("triangle", visible=False)
rocket.speed('fastest')
rocket.penup()
rocket.left(90)
rocket.setx(RADIUS)
rocket.showturtle()
rocket.pendown()
move_ISS()
move_rocket()
screen.exitonclick()
您可以随时单击窗口上的任意位置,以干净地退出事件处理程序的程序。我加入了一些逻辑,让太空船在它们停靠而不是飞过国际空间站后就粘在国际空间站上。
这也可以通过线程来完成,但所有图形操作都必须通过主线程进行引导以避免 Tkinter 错误(仅限 Python3 的解决方案):
from threading import Thread, active_count
from turtle import Turtle, Screen
from queue import Queue # use for thread-safe communications
from time import sleep
RADIUS = 250
ISS_DISTANCE = 3
ROCKET_DISTANCE = 4
CURSOR_SIZE = 20
QUEUE_SIZE = 1
def move_ISS(turtle):
while True:
actions.put((turtle.circle, RADIUS, ISS_DISTANCE))
sleep(0.1)
def move_rocket(turtle):
while True:
# rocket slows to ISS' speed once docked
distance = ISS_DISTANCE if rocket.distance(ISS) <= CURSOR_SIZE else ROCKET_DISTANCE
actions.put((turtle.circle, RADIUS, distance))
sleep(0.1)
def process_queue():
while not actions.empty():
action, *arguments = actions.get()
action(*arguments)
if active_count() > 1:
screen.ontimer(process_queue, 100)
actions = Queue(QUEUE_SIZE)
screen = Screen()
screen.title("ISS")
screen.setup(750, 750)
ISS = Turtle("square", visible=False)
ISS.speed('fastest')
ISS.penup()
ISS.left(180)
ISS.sety(RADIUS)
ISS.showturtle()
ISS.pendown()
ISS_thread = Thread(target=move_ISS, args=[ISS], daemon=True)
rocket = Turtle("triangle", visible=False)
rocket.speed('fastest')
rocket.penup()
rocket.left(90)
rocket.setx(RADIUS)
rocket.showturtle()
rocket.pendown()
rocket_thread = Thread(target=move_rocket, args=[rocket], daemon=True)
ISS_thread.start()
rocket_thread.start()
process_queue()
screen.exitonclick()