You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

嵌入Tkinter窗口的Turtle无响应,点击菜单无法绘图

问题描述

开发一款可绘制多种图形的程序,已成功将TurtleScreen嵌入Tkinter主窗口,并创建了Tkinter菜单触发不同图形绘制命令。但点击“Shapes”菜单中的任意图形选项,Turtle无任何动作,既不移动也不绘制图形,且无报错信息。

附上代码:

from tkinter import *
import turtle as t
import math
from tkinter import Menu
import ctypes

title = "Turtle printer"
button_width = 30
hypotenuse = 100
cathete = hypotenuse / math.sqrt(2)


class Main:
    def __init__(self):
        self.setup_root()

    def setup_root(self):
        self.root = Tk()
        self.root.attributes("-fullscreen", True)
        self.root.title(title)

        self.canvas = Canvas(self.root)
        self.canvas.pack()

        self.turtle_screen = t.TurtleScreen(self.canvas)
        self.turtle_screen._RUNNING = True  # Reactivate

        self.turtle = t.RawTurtle(self.turtle_screen)

        self.setup_turtle_screen()

        self.setup_file_menu()
        self.setup_shape_menu()

        self.root.mainloop()

    def exit_root(self):
        self.root.destroy()
        self.root.quit()

    def setup_file_menu(self):
        menu = Menu(self.root)
        self.root.config(menu=menu)
        filemenu = Menu(menu)
        filemenu.add_command(label="Exit", command=self.exit_root)

    def setup_shape_menu(self):
        menu = Menu(self.root)
        self.root.config(menu=menu)
        shapemenu = Menu(menu)
        menu.add_cascade(label="Shapes", menu=shapemenu)
        shapemenu.add_command(label="F", command=self.draw_f_shape)
        shapemenu.add_command(label="Square", command=self.draw_square)
        # Add more shape commands here

    def setup_turtle_screen(self):
        user32 = ctypes.windll.user32
        screen_width = user32.GetSystemMetrics(0)
        screen_height = user32.GetSystemMetrics(1)

        self.canvas.config(width=screen_width, height=screen_height)
        self.turtle_screen.screensize(screen_width, screen_height)
        self.turtle_screen.setworldcoordinates(0, 0, screen_width, screen_height)
        self.turtle_screen.tracer(0)

# Add shape drawing commands below

    def draw_f_shape(self):
        self.turtle.penup()
        self.turtle.goto(0, 0)
        self.turtle.pendown()

        self.turtle.left(90)
        self.turtle.forward(90)
        self.turtle.right(90)
        self.turtle.color("red")
        self.turtle.forward(60)
        self.turtle.back(60)

        self.turtle.left(90)
        self.turtle.color("black")
        self.turtle.forward(60)
        self.turtle.left(90)
        self.turtle.color("red")
        self.turtle.back(100)

        self.turtle.reset()
        self.turtle_screen.update()

    def draw_square(self):
        self.turtle.penup()
        self.turtle.goto(0, 0)
        self.turtle.pendown()

        for _ in range(4):
            self.turtle.forward(100)
            self.turtle.right(90)

        self.turtle.reset()
        self.turtle_screen.update()

Main()
解决方案

问题出在三个核心点,逐一修复即可:

  1. 菜单覆盖问题
    setup_file_menu和setup_shape_menu各自创建新的主菜单并覆盖root的菜单配置,导致菜单逻辑混乱。需要创建一个全局主菜单,两个子菜单都挂载到这个主菜单下。

  2. Turtle重置时机错误
    绘制完成后调用self.turtle.reset()会直接清除画布所有图形并重置Turtle状态,导致刚画好的图形立刻消失。如果需要每次绘制前清空画布,应在绘制开始前调用self.turtle.clear(),而非绘制后调用reset()。

  3. 退出逻辑顺序错误
    exit_root中先调用destroy()再调用quit()会触发报错,应先终止主循环再销毁窗口。


修改后的完整代码:

from tkinter import *
import turtle as t
import math
from tkinter import Menu
import ctypes

title = "Turtle printer"
button_width = 30
hypotenuse = 100
cathete = hypotenuse / math.sqrt(2)


class Main:
    def __init__(self):
        self.setup_root()

    def setup_root(self):
        self.root = Tk()
        self.root.attributes("-fullscreen", True)
        self.root.title(title)

        self.canvas = Canvas(self.root)
        self.canvas.pack(fill=BOTH, expand=True)  # 让画布自适应窗口

        self.turtle_screen = t.TurtleScreen(self.canvas)
        self.turtle_screen._RUNNING = True

        self.turtle = t.RawTurtle(self.turtle_screen)

        # 创建全局主菜单
        self.main_menu = Menu(self.root)
        self.root.config(menu=self.main_menu)

        self.setup_turtle_screen()
        self.setup_file_menu()
        self.setup_shape_menu()

        self.root.mainloop()

    def exit_root(self):
        self.root.quit()  # 先终止主循环
        self.root.destroy()  # 再销毁窗口

    def setup_file_menu(self):
        filemenu = Menu(self.main_menu, tearoff=0)
        filemenu.add_command(label="Exit", command=self.exit_root)
        self.main_menu.add_cascade(label="File", menu=filemenu)

    def setup_shape_menu(self):
        shapemenu = Menu(self.main_menu, tearoff=0)
        shapemenu.add_command(label="F", command=self.draw_f_shape)
        shapemenu.add_command(label="Square", command=self.draw_square)
        self.main_menu.add_cascade(label="Shapes", menu=shapemenu)

    def setup_turtle_screen(self):
        user32 = ctypes.windll.user32
        screen_width = user32.GetSystemMetrics(0)
        screen_height = user32.GetSystemMetrics(1)

        self.canvas.config(width=screen_width, height=screen_height)
        self.turtle_screen.screensize(screen_width, screen_height)
        self.turtle_screen.setworldcoordinates(0, 0, screen_width, screen_height)
        self.turtle_screen.tracer(0)  # 关闭自动刷新,手动控制

    def draw_f_shape(self):
        self.turtle.clear()  # 绘制前清空画布
        self.turtle.penup()
        self.turtle.goto(0, 0)
        self.turtle.pendown()
        self.turtle.setheading(0)  # 重置朝向,避免之前的方向影响

        self.turtle.left(90)
        self.turtle.forward(90)
        self.turtle.right(90)
        self.turtle.color("red")
        self.turtle.forward(60)
        self.turtle.back(60)

        self.turtle.left(90)
        self.turtle.color("black")
        self.turtle.forward(60)
        self.turtle.left(90)
        self.turtle.color("red")
        self.turtle.back(100)

        self.turtle_screen.update()  # 手动刷新显示

    def draw_square(self):
        self.turtle.clear()  # 绘制前清空画布
        self.turtle.penup()
        self.turtle.goto(0, 0)
        self.turtle.pendown()
        self.turtle.setheading(0)  # 重置朝向

        for _ in range(4):
            self.turtle.forward(100)
            self.turtle.right(90)

        self.turtle_screen.update()  # 手动刷新显示

Main()

额外优化:

  • 给画布添加fill=BOTH, expand=True,确保画布填满整个窗口
  • 绘制前添加setheading(0)重置Turtle朝向,避免多次绘制后方向混乱

内容的提问来源于stack exchange,提问作者Akemi

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.12 13:50:40