【问题标题】:"Stop" Button in TkinterTkinter 中的“停止”按钮
【发布时间】:2019-04-18 22:41:13
【问题描述】:

我正在尝试让海龟动画以按钮开始并以按钮停止。从一个按钮开始很容易,但我似乎无法找出一个停止按钮?到目前为止,这是我的代码:

import turtle
import tkinter as tk
def start():
    t.forward(100)
    t.right(90)
    t.forward(100)
    t.left(90)
    t.forward(100)
    t.right(90)
    t.forward(100)
    t.right(90)
    t.forward(100)

def stop():
    t.stop

def clear():
    canvas.delete("all")

root = tk.Tk()
canvas = tk.Canvas(width = 500, height = 500)
canvas.pack()

t = turtle.RawTurtle(canvas)

tk.Button(text = "Start", command = start).pack(side = tk.LEFT)
tk.Button(text = "Stop", command = stop).pack(side = tk.LEFT)
tk.Button(text = "Clear", command = clear).pack(side = tk.LEFT)

root.mainloop()

清除按钮也有效,但之后开始按钮不再有效。如果有人也可以帮助我。

感谢@Mike - SMT 帮助我编写此代码。这是经过编辑且功能齐全的代码:

import turtle
import tkinter as tk


def start(turtle_object, draw_path):
    global tracker, start_ndex, end_ndex, started
    tracker = False
    if started == False:
        started = True
        for i in range(start_ndex, end_ndex):
            if tracker == False and i <= end_ndex:
                pth = draw_path[i]
                if pth[0] == "f":
                    turtle_object.forward(pth[1])
                elif pth[0] == "r":
                    turtle_object.right(pth[1])
                elif pth[0] == "l":
                    turtle_object.left(pth[1])
                start_ndex += 1


running = True

def stop():
    global tracker, started
    tracker = True
    started = False

def clear():
    global t, tracker, started, start_ndex
    t.reset()
    start_ndex = 0
    started = False
    t = turtle.RawTurtle(canvas)


root = tk.Tk()
tracker = False
start_ndex = 0
started = False # added this tracking variable to prevent issues with     spamming the start button.

draw_path = [["f", 100], ["r", 90], ["f", 100], ["l", 90], ["f", 100], ["r", 90], ["f", 100], ["r", 90], ["f", 100]]


end_ndex = len(draw_path)

canvas = tk.Canvas(width = 500, height = 500)
canvas.pack()

t = turtle.RawTurtle(canvas)
tk.Button(text = "Start", command = lambda: start(t, draw_path)).pack(side = tk.LEFT)
tk.Button(text = "Stop", command = stop).pack(side = tk.LEFT)
tk.Button(text = "Clear", command = clear).pack(side = tk.LEFT)
root.mainloop()

【问题讨论】:

标签: python tkinter turtle-graphics tkinter-canvas


【解决方案1】:

除非您在每条绘制的线之间提供检查器,否则您无法停止每个绘制语句。

下面的代码只是一个粗略的模拟,您可以制作一些东西来检查用于告诉它不再绘制新线的跟踪变量。

你可以做的最接近停止绘图的事情是这样的:

import turtle
import tkinter as tk

def start():
    global tracker
    tracker = False
    if tracker == False:
        t.forward(100)
    if tracker == False:
        t.right(90)
    if tracker == False:
        t.forward(100)
    if tracker == False:
        t.left(90)
    if tracker == False:
        t.forward(100)
    if tracker == False:
        t.right(90)
    if tracker == False:
        t.forward(100)
    if tracker == False:
        t.right(90)
    if tracker == False:
        t.forward(100)


def stop():
    global tracker
    tracker = True

def clear():
    canvas.delete("all")

root = tk.Tk()
tracker = False
canvas = tk.Canvas(width = 500, height = 500)
canvas.pack()

t = turtle.RawTurtle(canvas)

tk.Button(text = "Start", command = start).pack(side = tk.LEFT)
tk.Button(text = "Stop", command = stop).pack(side = tk.LEFT)
tk.Button(text = "Clear", command = clear).pack(side = tk.LEFT)

root.mainloop()

这至少会在每条线之后停止绘制,但您不能停止中线绘制。

只是为了好玩,如果我们添加一些跟踪变量并使用一些更清晰的逻辑,我们可以开始、停止和重新开始。

更新:从下面@cdlane 的评论中,我添加了添加跟踪并更新了清除功能。这应该允许启动停止启动没有问题,并且还能够清除该字段。

import turtle
import tkinter as tk

def start(turtle_object, draw_path):
    global tracker, start_ndex, end_ndex, started
    tracker = False
    if started == False:
        started = True
        for i in range(start_ndex, end_ndex):
            if tracker == False and i <= end_ndex:
                pth = draw_path[i]
                if pth[0] == "f":
                    turtle_object.forward(pth[1])
                elif pth[0] == "r":
                    turtle_object.right(pth[1])
                elif pth[0] == "l":
                    turtle_object.left(pth[1])
                start_ndex += 1

def stop():
    global tracker, started
    tracker = True
    started = False

def clear():
    global t, tracker, started, start_ndex
    canvas.delete("all")
    tracker = False
    start_ndex = 0
    started = False
    t = turtle.RawTurtle(canvas)

root = tk.Tk()
tracker = False
start_ndex = 0
started = False # added this tracking variable to prevent issues with spamming the start button.

draw_path = [["f", 100], ["r", 90], ["f", 100], ["l", 90], ["f", 100], ["r", 90], ["f", 100], ["r", 90], ["f", 100]]


end_ndex = len(draw_path)

canvas = tk.Canvas(width = 500, height = 500)
canvas.pack()

t = turtle.RawTurtle(canvas)
tk.Button(text = "Start", command = lambda: start(t, draw_path)).pack(side = tk.LEFT)
tk.Button(text = "Stop", command = stop).pack(side = tk.LEFT)
tk.Button(text = "Clear", command = clear).pack(side = tk.LEFT)
root.mainloop()

【讨论】:

  • 在您的可重启解决方案中,有几个问题。首先,它分享了 OP 原版的“无法从‘清除’中恢复”的问题。其次,如果你的速度足够快,可以在运行过程中多次单击“开始”,乌龟就会误入歧途。不是吹毛求疵,只是想看看您如何处理我在自己的解决方案中遇到的问题。
  • @cdlane 我同意我的解决方案存在局限性。我会看看我是否能想出更好的解决方案来应对其他问题。
  • @cdlane 我已经更新了我的第二个解决方案来应对你提到的问题。我想象我可能会建造一些更干净但有时又快又脏的东西:D
  • 很好——它现在运行稳定!海龟库保存了它创建的海龟的内部列表,因此它们实际上永远不会被垃圾收集。如果可以的话,最好重复使用海龟,而不是分配新的。这与您的 clear() 方法有关。
  • @cdlane 嗡嗡声。我以前从未使用过海龟,也不知道它是如何记住每只海龟的。在这种情况下你会怎么做?
【解决方案2】:

我同意@Mike-SMT 回答中的想法,但我会以不同的方式进行。乌龟和它的控件对我来说看起来很像一个 Python 生成器,所以我把它改成了这样。海龟沿着一条路径移动,一次一个像素,产生可能返回或不返回的控制。或者它可能会耗尽它的路径并停止迭代:

import tkinter as tk
from turtle import RawTurtle

PATH = [(100.00, 0.00), (100.00, -100.00), (200.00, -100.00), (200.00, -200.00), (100.00, -200.00)]

def run():
    for position in PATH:
        turtle.setheading(turtle.towards(position))

        while turtle.distance(position) > 1:
            turtle.forward(1)
            yield

def start():
    global generator, running

    running = True

    while running:
        try:
            next(generator)

        except ValueError:  # user clicked start but already running
            return

        except TypeError:  # new run
            turtle.reset()
            generator = run()

        except StopIteration:  # end of complete run
            generator = None
            running = False
            break

def stop():
    global running
    running = False

def clear():
    global generator
    turtle.reset()
    generator = None

root = tk.Tk()
canvas = tk.Canvas(width=500, height=500)
canvas.pack()

turtle = RawTurtle(canvas, "turtle")

running = True
generator = None

tk.Button(text="Start", command=start).pack(side=tk.LEFT, expand=tk.TRUE)
tk.Button(text="Stop", command=stop).pack(side=tk.LEFT, expand=tk.TRUE)
tk.Button(text="Clear", command=clear).pack(side=tk.LEFT, expand=tk.TRUE)

root.mainloop()

清除按钮也有效,但之后开始按钮无效 工作了。如果有人也可以帮助我。

您可以将当前的clear() 函数替换为:

def clear():
    t.clear()

如果您只想擦除已绘制的路径,但将海龟留在最终位置。如果您想擦除路径并将海龟重置回起点,请执行以下操作:

def clear():
    t.reset()

【讨论】:

  • 我尝试了这个命令,但是缩进('return')有一些问题,我尝试通过用turtle.reset()替换return来修复,但是没有定义'generator'出现问题在 Next(generator) 行中。
  • @Pokyzard,确实出现了一个奇怪的缩进,所以我修复并重新加载了示例代码。我从这个网页复制了一份并粘贴到一个文件中,中间没有使用编辑器,它运行良好。再试一次。 (我假设您正在使用 Python 3,基于您导入的 tkinter 具有较低的 't'。)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-01-26
  • 1970-01-01
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-11
相关资源
最近更新 更多