使用threading.Timer修改turtle坐标时报main thread is not in main loop错误如何解决
问题根因
turtle 所有界面相关操作都要求必须在主线程的主循环内执行,你用到的threading.Timer会启动独立子线程,子线程中调用person.sety()修改海龟属性就会触发「main thread is not in main loop」报错。
最简解决方案
直接用 turtle 内置的ontimer接口替代多线程定时器即可,这个接口原生在主循环中调度延迟任务,不需要额外处理线程和队列逻辑,仅需修改少量代码:
- 移除
from threading import Timer导入 - 把原
personYY函数里的 Timer 启动逻辑替换为wn.ontimer(回调函数, 延迟毫秒数) - 可以根据你的需求调整
fallToFloor的实现,如果你要的是2秒后直接重置到y=0位置,直接修改sety(0)即可。
修改后的完整可运行代码如下:
import turtle wn = turtle.Screen() wn.title("my game") wn.bgcolor("blue") wn.setup(width=1000, height=800) wn.tracer(0) # 角色定义 person = turtle.Turtle() person.speed(0) person.shape("square") person.color("white") person.shapesize(stretch_wid=1, stretch_len=1) person.penup() person.goto(-350, 0) def personXX(): x = person.xcor() x += 20 person.setx(x) def personXY(): x = person.xcor() x -= 20 person.setx(x) def personYY(): y = person.ycor() y += 20 person.sety(y) # 用turtle内置的ontimer调度,2000毫秒=2秒后执行fallToFloor wn.ontimer(fallToFloor, 2000) def fallToFloor(): # 2秒后直接重置到y=0位置 person.sety(0) # 如果要模拟慢慢下落的效果,可以替换成下面的逻辑 # if person.ycor() > 0: # person.sety(person.ycor() - 5) # wn.ontimer(fallToFloor, 50) wn.listen() wn.onkeypress(personXY, "a") wn.onkeypress(personXX, "d") wn.onkeypress(personYY, "space") while True: wn.update()
可选优化(更真实的重力效果)
如果想要持续的重力效果,不需要每次跳都开定时器,可以直接在主循环里加重力逻辑:
- 定义全局变量
gravity = -0.5、y_velocity = 0 - 每次按空格的时候给
y_velocity赋值向上的初速度,比如y_velocity = 10 - 主循环每次更新时执行
y_velocity += gravity,再把角色y坐标加上y_velocity,碰到地面时重置y坐标和速度即可
内容的提问来源于stack exchange,提问作者David Lublink
相关产品推荐
相关产品推荐

