我知道我的问题听起来很像以前的许多问题,但是老实说我不能在我的程序上下文中弄清楚它。我有一个Collatz猜想的算法,我想通过Tkinter GUI运行(一切都可以在终端上正常运行)。我试图将相关函数绑定到Return键和按钮上,但是遇到相同的错误两种输入数据方法的提示信息,我将在下面显示。如果通过终端输入,我的输出将在GUI上完美运行。
我尝试过的方法最好通过下面的代码来解释。 (####行上方的代码主要与使GUI出现在我的Spyder IDE上而不是隐藏在它的后面有关。)
代码:
from tkinter import *
root = Tk()
import os
import subprocess
import platform
def raise_app(root: Tk):
root.attributes("-topmost", True)
if platform.system() == 'Darwin':
tmpl = 'tell application "System Events" to set frontmost of every process whose unix id is {} to true'
script = tmpl.format(os.getpid())
output = subprocess.check_call(['/usr/bin/osascript', '-e', script])
root.after(0, lambda: root.attributes("-topmost", False))
########################################################################
lst = []
def collatz(num):
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
def main(event):
collatz(num)
#Input Box
input = Entry(root, width = 10, bg = "light grey")
input.grid(row = 0, column = 0, sticky = W)
input.get()
input.bind("<Return>", main)
##Button
#button1 = Button(root, width = 10, text = "Run", command = main)
#button1.grid(row = 1, column = 0, sticky = W)
##Output box
output1 = Text(root, width = 100, height = 10, bg = "light grey")
output1.grid(row = 3, column = 0, sticky = W)
output2 = Text(root, width = 50, height = 1, bg = "white")
output2.grid(row = 2, column = 0, sticky = W)
output1.insert(END, lst)
output2.insert(END, "Number of iterations are: " + str(len(lst)))
########################################################################
raise_app(root)
root.mainloop()
按原样运行代码时,会出现输入框,但是当我单击return时,会出现错误消息:
Exception in Tkinter callback
Traceback (most recent call last):
File "/anaconda3/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/Users/andrehuman/Desktop/Python/programs/Collatz Conjecture/Collatz_alt3.py", line 43, in main
collatz(num)
NameError: name 'num' is not defined
如果我尝试将按钮链接到“主要”功能,则完全相同。
当我注释输入并按下按钮,然后通过终端输入数字时,一切都会按预期进行。迭代编号的列表应出现在文本框中。 (而且我什至可以得到Matplotlib图,以便在终端中直观地显示数据。)如果可以解决此问题,我想尝试在GUI中显示(或嵌入)Matplotlib图。
反正就是这样。任何帮助将不胜感激。
安德烈·人类
答案 0 :(得分:2)
name 'num' is not defined
的原因是您正在调用collatz(num)
,但是当您说num
时,程序无法理解您指的是什么值。您应该在使用该名称之前为其分配一个值。我假设您希望该值成为input
框中的内容。
def main(event):
num = int(input.get())
collatz(num)
您还需要将output1.insert
和output2.insert
行复制到main
的内部。现在,这些行在窗口甚至没有显示给用户之前就已执行,因此它们无法输入足够快的数字以使collatz
在文本被写入之前触发。并且在事实结束后更改lst
不会对文本产生任何影响,因为它不够聪明,无法注意到列表已更改。
def main(event):
num = int(input.get())
collatz(num)
#delete previous contents of text boxes
output1.delete(1.0, END)
output2.delete(1.0, END)
output1.insert(END, lst)
output2.insert(END, "Number of iterations are: " + str(len(lst)))
另一个问题是,对collatz
的连续调用将导致lst
不断增长,因为先前调用中的列表内容仍然存在。尝试在文本框中输入4
,然后按Enter几次。输出将从2变为4到6 ...这是不对的。
使用可变全局状态时,这是自然危险。一种可能的解决方案是在每个collatz调用开始时重置lst
。
def collatz(num):
lst.clear()
#rest of function goes here
...但是我更倾向于将lst
设置为该函数的局部变量,并在最后将其返回。
def collatz(num):
lst = []
while num != 1:
lst.append(num)
if num % 2 == 0:
num = int(num / 2)
else:
num = int(3 * num + 1)
return lst
def main(event):
num = int(input.get())
lst = collatz(num)
#delete previous contents of text boxes
output1.delete(1.0, END)
output2.delete(1.0, END)
output1.insert(END, lst)
output2.insert(END, "Number of iterations are: " + str(len(lst)))
#later, just before mainloop is called...
#lst doesn't exist in this scope, so just set the text to a literal value
output1.insert(END, "[]")
output2.insert(END, "Number of iterations are: 0")