如何为 Turtle tkinter 制作重启按钮? (海龟、Tkinter、希尔伯特曲线)
How to make restart button for Turtle tkinter? (Turtle, Tkinter, hilbert curve)
我目前正在做一个小项目,在这个项目中,用户可以在 GUI 上输入希尔伯特曲线的第 n 次迭代,该曲线将用乌龟绘制并显示在同一个 window(不打开一个新的)。我有一个计算按钮,它似乎工作正常,还有一个重启按钮,它应该清除屏幕并将 Turtle 重置为其初始状态。这目前仅在 n 的计算过程已经完成并且绘图也已完成时才有效。因此,当您尝试在 turtle 仍在绘制时重置 function/process 时,它会发疯。我想我必须重新定义我的 clear 函数,否则我似乎很容易错过一些东西。我想我必须在那里做一个条件语句,如果过程(主要)未完成,那么做这个和那个。想不出来,希望得到帮助。
代码如下(希望德语不影响理解):
""" Projektabgabe Python """
import turtle
import tkinter as tk
from tkinter import messagebox
""" Fenster-Deklaration und Umgebung """
window = tk.Tk()
window.title("Hilbert-Kurve")
window.geometry("600x600")
canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()
""" RawTurtle um Turtle mit Tkinter zu verbinden """
s = turtle.TurtleScreen(canvas)
t = turtle.RawTurtle(canvas)
""" Eingabefeld für Benutzereingabe """
eingabe_n = tk.Entry(window)
eingabe_n.pack()
""" Funktion der Hilbert-Kurve """
def hilbert(n, angle, step):
""" Diese Funktion berechnet rekursiv die Hilbert-Kurve der n-ten Iterationsstufe.
n: n-te Iterationsstufe der Hilbert-Kurve
angle: der Winkel der Abzweigung, in main wird diese nach Definition der "Kurve" auf 90 gesetzt.
step: bezeichnet Schrittlänge (in Pixel) die Turtle nach geg. n hinterlegt.
Ausgabe: Hilbert-Kurve der n-ten Iterationsstufe. """
# Wenn Höhe 0, gebe nichts zurück
if n == 0:
return None
# Turtle dreht sich nach links um 90 Grad
t.left(angle)
hilbert(n-1, -angle, step)
t.forward(step)
t.right(angle)
hilbert(n-1, angle, step)
t.forward(step)
hilbert(n-1, angle, step)
t.right(angle)
t.forward(step)
hilbert(n-1, -angle, step)
t.left(angle)
""" Main-Funktion zur Ausgabe der Benutzereingabe
In diesem Beispiel wurde die Skalierung der Kurve auf size = 250 gesetzt. """
def main():
# Wenn nichts in Eingabebox eingegeben, Fehlermeldung bzw. Infobox
if len(eingabe_n.get())==0:
messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")
n = int(eingabe_n.get())
if n > 3:
t.speed("fastest")
# Wenn Eingabe 0, Fehlermeldung bzw. Infobox
if n == 0:
messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")
t.reset()
# size bezeichnet die Skalierung der abzubildenen Hilbertkurve
size = 400
t.penup() # Bewege Turtle ohne zu zeichnen
# Koordinaten (x,y) je nach size berechnen
t.goto(-size / 2, -size / 2) # x = -400/2 und y = -400/2
# Absetzen von Turtle, da Position gefunden
t.pendown()
""" Wenn man in der Hilbert-Kurve ein Segment |_| hat, dann ist dessen Kantenlänge aller drei Kanten die stepsize und am
Anfang ist die 1 wenn wir den Kasten auf 1 normieren (oder 400 wenn size=400). Dann unterteilt man das Segment ja
in ein Raster mit 4x4 Punkten, zwischen denen man die neuen Linien zieht. Im Endeffekt die Anzahl der Punkte in dem
Gitter auf der gesamten Kantenlänge in jedem Schritt verdoppelt, daher ist die Anzahl der Gitterpunkte auf Level n
dann 2ⁿ. Wenn man zwei nebeneinander liegende Gitterpunkte verbindet (weil sie verschmelzen), kommt man auf 2^n-1 Verbindungslinien.
Also teilt man die Gesamtstrecke durch 2^n-1 und skaliert das ganze auf die Seitenlänge des Fensters, also
gerade: size/ 2**n-1. """
hilbert(n, 90, size/(2 ** n-1))
""" Reset-Funktion """
def clearFunc():
s.clearscreen()
u = turtle.RawTurtle(canvas)
t = u
""" Button-Deklarierung
button_n: Bezeichner für den Berechnen Button
reset_button: Bezeichner für den Reset (zurücksetzen) Button """
button_n = tk.Button(window, text="Berechnen",command=main)
button_n.pack()
reset_button = tk.Button(window, text="Reset", command=clearFunc)
reset_button.pack()
""" Fenster Funktion """
window.mainloop()
你的问题是 Hilbert 是递归的,在它到达 n==0 的结尾之前没有任何东西可以阻止它。
我发现规避此问题的唯一方法如下:
我们定义了一个名为 Flag 的全局布尔变量,它将携带我们要停止的信息。
我的建议涉及 3 处修改,如下所示:
在“main()”部分:
def main():
global Flag; Flag=False
在“希尔伯特(...)”部分:
# Wenn Höhe 0, gebe nichts zurück
if Flag or n == 0:
return None
最后,在“clearFunc()”部分:
def clearFunc():
global Flag; Flag=True
我做了这 3 处修改,它解决了您的问题(据我了解)。请注意,此辅助变量的全局性质是必不可少的。
我目前正在做一个小项目,在这个项目中,用户可以在 GUI 上输入希尔伯特曲线的第 n 次迭代,该曲线将用乌龟绘制并显示在同一个 window(不打开一个新的)。我有一个计算按钮,它似乎工作正常,还有一个重启按钮,它应该清除屏幕并将 Turtle 重置为其初始状态。这目前仅在 n 的计算过程已经完成并且绘图也已完成时才有效。因此,当您尝试在 turtle 仍在绘制时重置 function/process 时,它会发疯。我想我必须重新定义我的 clear 函数,否则我似乎很容易错过一些东西。我想我必须在那里做一个条件语句,如果过程(主要)未完成,那么做这个和那个。想不出来,希望得到帮助。
代码如下(希望德语不影响理解):
""" Projektabgabe Python """
import turtle
import tkinter as tk
from tkinter import messagebox
""" Fenster-Deklaration und Umgebung """
window = tk.Tk()
window.title("Hilbert-Kurve")
window.geometry("600x600")
canvas = tk.Canvas(master=window, width=500, height=500)
canvas.pack()
""" RawTurtle um Turtle mit Tkinter zu verbinden """
s = turtle.TurtleScreen(canvas)
t = turtle.RawTurtle(canvas)
""" Eingabefeld für Benutzereingabe """
eingabe_n = tk.Entry(window)
eingabe_n.pack()
""" Funktion der Hilbert-Kurve """
def hilbert(n, angle, step):
""" Diese Funktion berechnet rekursiv die Hilbert-Kurve der n-ten Iterationsstufe.
n: n-te Iterationsstufe der Hilbert-Kurve
angle: der Winkel der Abzweigung, in main wird diese nach Definition der "Kurve" auf 90 gesetzt.
step: bezeichnet Schrittlänge (in Pixel) die Turtle nach geg. n hinterlegt.
Ausgabe: Hilbert-Kurve der n-ten Iterationsstufe. """
# Wenn Höhe 0, gebe nichts zurück
if n == 0:
return None
# Turtle dreht sich nach links um 90 Grad
t.left(angle)
hilbert(n-1, -angle, step)
t.forward(step)
t.right(angle)
hilbert(n-1, angle, step)
t.forward(step)
hilbert(n-1, angle, step)
t.right(angle)
t.forward(step)
hilbert(n-1, -angle, step)
t.left(angle)
""" Main-Funktion zur Ausgabe der Benutzereingabe
In diesem Beispiel wurde die Skalierung der Kurve auf size = 250 gesetzt. """
def main():
# Wenn nichts in Eingabebox eingegeben, Fehlermeldung bzw. Infobox
if len(eingabe_n.get())==0:
messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")
n = int(eingabe_n.get())
if n > 3:
t.speed("fastest")
# Wenn Eingabe 0, Fehlermeldung bzw. Infobox
if n == 0:
messagebox.showinfo(title=None, message="Geben Sie eine natürliche Zahl größer 0 ein.")
t.reset()
# size bezeichnet die Skalierung der abzubildenen Hilbertkurve
size = 400
t.penup() # Bewege Turtle ohne zu zeichnen
# Koordinaten (x,y) je nach size berechnen
t.goto(-size / 2, -size / 2) # x = -400/2 und y = -400/2
# Absetzen von Turtle, da Position gefunden
t.pendown()
""" Wenn man in der Hilbert-Kurve ein Segment |_| hat, dann ist dessen Kantenlänge aller drei Kanten die stepsize und am
Anfang ist die 1 wenn wir den Kasten auf 1 normieren (oder 400 wenn size=400). Dann unterteilt man das Segment ja
in ein Raster mit 4x4 Punkten, zwischen denen man die neuen Linien zieht. Im Endeffekt die Anzahl der Punkte in dem
Gitter auf der gesamten Kantenlänge in jedem Schritt verdoppelt, daher ist die Anzahl der Gitterpunkte auf Level n
dann 2ⁿ. Wenn man zwei nebeneinander liegende Gitterpunkte verbindet (weil sie verschmelzen), kommt man auf 2^n-1 Verbindungslinien.
Also teilt man die Gesamtstrecke durch 2^n-1 und skaliert das ganze auf die Seitenlänge des Fensters, also
gerade: size/ 2**n-1. """
hilbert(n, 90, size/(2 ** n-1))
""" Reset-Funktion """
def clearFunc():
s.clearscreen()
u = turtle.RawTurtle(canvas)
t = u
""" Button-Deklarierung
button_n: Bezeichner für den Berechnen Button
reset_button: Bezeichner für den Reset (zurücksetzen) Button """
button_n = tk.Button(window, text="Berechnen",command=main)
button_n.pack()
reset_button = tk.Button(window, text="Reset", command=clearFunc)
reset_button.pack()
""" Fenster Funktion """
window.mainloop()
你的问题是 Hilbert 是递归的,在它到达 n==0 的结尾之前没有任何东西可以阻止它。 我发现规避此问题的唯一方法如下: 我们定义了一个名为 Flag 的全局布尔变量,它将携带我们要停止的信息。
我的建议涉及 3 处修改,如下所示:
在“main()”部分:
def main():
global Flag; Flag=False
在“希尔伯特(...)”部分:
# Wenn Höhe 0, gebe nichts zurück
if Flag or n == 0:
return None
最后,在“clearFunc()”部分:
def clearFunc():
global Flag; Flag=True
我做了这 3 处修改,它解决了您的问题(据我了解)。请注意,此辅助变量的全局性质是必不可少的。