简体   繁体   English

Tkinter 中的“停止”按钮

[英]"Stop" Button in Tkinter

I'm trying to have a turtle animation start with a button and stop with a button.我正在尝试让海龟动画以按钮开始并以按钮停止。 It's very easy to start with a button but I can't seem to be able to figure out a stop button?从按钮开始很容易,但我似乎无法找出停止按钮? Here's my code so far:到目前为止,这是我的代码:

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

Also the clear button works but afterwards the start button doesn't work anymore.清除按钮也有效,但之后开始按钮不再有效。 If someone can help me with that as well.如果有人也可以帮助我。

Thank you to @Mike - SMT for helping me with this code.感谢@Mike - SMT 帮助我处理此代码。 Here's the edited and fully functioning code:这是经过编辑且功能齐全的代码:

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

You cannot stop each draw statement unless you provide a checker in between each line drawn.除非您在绘制的每条线之间提供检查器,否则您无法停止每个绘制语句。

The below code is just a rough mock up of how you could make something to check for a tracking variable used to tell it to no longer draw new lines.下面的代码只是一个粗略的模型,你可以做一些事情来检查跟踪变量,用于告诉它不再绘制新线。

The closest thing you can do to being able to stop drawing is something like this:您可以做的最接近停止绘图的事情是这样的:

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

This will at least stop drawing after each line but you cannot stop mid line draw.这至少会在每条线之后停止绘制,但您不能停止绘制中线。

Just for the fun of it if we add some tracking variables and use some cleaner logic we can start, stop and start again.只是为了好玩,如果我们添加一些跟踪变量并使用一些更清晰的逻辑,我们就可以开始、停止和重新开始。

Update: From @cdlane's comment below I have added addition tracking and updated the clear function.更新:从@cdlane 下面的评论中,我添加了附加跟踪并更新了清除功能。 This should allow for start stop start without issues and also be able to clear the field.这应该允许启动停止启动而不会出现问题,并且还能够清除该字段。

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

I agree with the ideas in @Mike-SMT's answer but I'd go about it a different way.我同意@Mike-SMT 回答中的想法,但我会以不同的方式进行。 The turtle and its controls seem very much like a Python generator to me so I've recast it as such.海龟和它的控件对我来说看起来很像一个 Python 生成器,所以我把它改成了这样。 The turtle moves along a path, one pixel at a time, yielding control which may, or may not return.海龟沿着一条路径移动,一次一个像素,产生可能返回也可能不返回的控制权。 Or it may exhaust its path and stop the iteration:或者它可能会耗尽其路径并停止迭代:

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

Also the clear button works but afterwards the start button doesn't work anymore.清除按钮也有效,但之后开始按钮不再有效。 If someone can help me with that as well.如果有人也可以帮助我。

You can replace your current clear() function with:您可以将当前的clear()函数替换为:

def clear():
    t.clear()

if you just want to erase the path that's been drawn but leave the turtle where it ended up.如果您只想擦除已绘制的路径但将乌龟留在它结束的位置。 If you want to erase the path and reset the turtle back to the starting point, instead do:如果要擦除路径并将海龟重置回起点,请执行以下操作:

def clear():
    t.reset()

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM