更新 tkinter 标签并使用条目选择参数
Update tkinter label and use entry to choose parameter
我做了一个小脚本来练习tkinter的使用。我希望程序打开一个 window 并显示一个标签。按下按钮后,标签应显示 0 到 100 之间的随机数。我还希望标签每秒刷新一次并显示另一个随机数。
from tkinter import *
import random
import time
root = Tk()
def getrandint():
result = random.randint(0, 100)
return result
def go():
lab2['text'] = 'Number: ' + str(getrandint())
lab2.pack()
root.geometry('300x200')
root.mainloop()
time.sleep(1)
go()
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
#ent = Entry(root, width=20)
#number = ent.get()
b = Button(root, text='Go', command=go())
b.pack()
lab1.pack()
lab2.pack()
#ent.pack()
这就是我的进展。它会打开一个 window 并显示一个随机数,但不会刷新该数字。按钮甚至没有显示。此外,当我关闭 window 时,Python 3.8 向我显示此错误消息:
Traceback (most recent call last):
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 102, in <module>
b = Button(root, text='Go', command=go())
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 95, in go
go()
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 89, in go
lab2['text'] = 'Number: ' + str(getrandint())
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1660, in __setitem__
self.configure({key: value})
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1649, in configure
return self._configure('configure', cnf, kw)
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1639, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!label2"
最后,有没有办法把random.randint(0, b)的第二个参数改成入口和开头的按钮?
首先,当您将命令传递给按钮时,您需要将函数放在不带括号的位置:command=go
。如果您使用括号,该函数将在您声明按钮时调用,而不是在您按下按钮时调用。
其次,您不应在按下按钮后调用 root.mainloop()。你应该 运行 在文件末尾。
mainloop
永远不会 returns,所以在后面放置 sleep
和函数调用没有帮助。如果你想在主循环中 运行 编码,创建一个循环调用 tk.update()
和 tk.update_idletasks()
.
我认为更新的元素不需要再次打包更新。
最后,你为什么要从内部调用 go
?
from tkinter import *
import random
import time
root = Tk()
def getrandint():
result = random.randint(0, 100)
return result
def go():
lab2['text'] = 'Number: ' + str(getrandint())
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
#ent = Entry(root, width=20)
#number = ent.get()
b = Button(root, text='Go', command=go)
b.pack()
lab1.pack()
lab2.pack()
#ent.pack()
root.geometry('300x200')
root.mainloop()
让我们从基本错误开始,您对 mainloop()
的放置决定了所有小部件的显示内容(在编写良好的代码上)。在这种情况下,您想将 mainloop()
放在末尾。在你的情况下,这甚至可以工作,因为你正在使用 ()
和具有包含 mainloop()
功能的按钮(通过文字解释有点棘手:P)。
接下来是,您不应该使用 ()
为您的按钮调用该函数,因为它会自动启动该函数并且不会等待按下按钮:
b = Button(root, text='Go', command=go)
- 下一步是修复您的入口小部件和事件驱动编程。您不应该在代码开头接受用户的输入,因为它在开头是空的。您应该在触发事件(一个函数左右)后获取输入并将其存储在变量中,这意味着您的
getrandint()
将是:
def getrandint():
try: # To ignore if non integers are entered into the entry widget
result = random.randint(0, int(ent.get())) # Get the text from entry widget
return result
except TypeError: # Ignore the error
pass
- 接下来要避免使用
time.sleep()
,因为它会使 GUI 滞后。所以你应该改用 root.after(ms,func)
,它将在指定的 ms
: 之后调用 func
def go():
lab2['text'] = 'Number: ' + str(getrandint())
root.after(1000,go) # Repeat the function after 1 second
所以你的最终代码是:
from tkinter import *
import random
root = Tk()
root.geometry('300x200')
def getrandint():
try:
result = random.randint(0, int(ent.get()))
return result
except TypeError:
pass
def go():
lab2['text'] = 'Number: ' + str(getrandint())
root.after(1000,go)
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
ent = Entry(root, width=20)
b = Button(root, text='Go', command=go)
b.pack()
lab1.pack()
lab2.pack()
ent.pack()
root.mainloop() # At the end of the code
另请注意:
您可以通过将 go()
更改为:
来完全摆脱您的 getrandint()
def go():
try: # If not an integer is entered into entry widget
lab2['text'] = 'Number: ' + str(random.randint(0,int(ent.get())))
root.after(1000,go)
except ValueError: # Ignore the error
pass
综上所述,您的错误是由于您的代码流动方式造成的。经常练习记住这些,你将永远不会再看到这些错误 ;)
根据您的说明编写的程序应如下所示(类似):
from tkinter import *
import random
import time
# Create function, which generates random number and update label
def set_random_num():
num = random.randint(0,100)
lab2.config(text=num)
# Initialize tkinter window
root = Tk()
# Create labels and button
lab1 = Label(root, text='Type in number')
lab1.pack()
lab2 = Label(root, text='Number:')
lab2.pack()
b = Button(root, text='Go', command=lambda: set_random_num())
b.pack()
# Keep it at the end of program
root.mainloop()
Lambda
函数允许您正确调用您的函数。我建议为 tkinter 寻找一些好的教程。试试 this.
我做了一个小脚本来练习tkinter的使用。我希望程序打开一个 window 并显示一个标签。按下按钮后,标签应显示 0 到 100 之间的随机数。我还希望标签每秒刷新一次并显示另一个随机数。
from tkinter import *
import random
import time
root = Tk()
def getrandint():
result = random.randint(0, 100)
return result
def go():
lab2['text'] = 'Number: ' + str(getrandint())
lab2.pack()
root.geometry('300x200')
root.mainloop()
time.sleep(1)
go()
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
#ent = Entry(root, width=20)
#number = ent.get()
b = Button(root, text='Go', command=go())
b.pack()
lab1.pack()
lab2.pack()
#ent.pack()
这就是我的进展。它会打开一个 window 并显示一个随机数,但不会刷新该数字。按钮甚至没有显示。此外,当我关闭 window 时,Python 3.8 向我显示此错误消息:
Traceback (most recent call last):
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 102, in <module>
b = Button(root, text='Go', command=go())
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 95, in go
go()
File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py", line 89, in go
lab2['text'] = 'Number: ' + str(getrandint())
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1660, in __setitem__
self.configure({key: value})
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1649, in configure
return self._configure('configure', cnf, kw)
File "C:\Users\chris\AppData\Local\Programs\Python\Python38\lib\tkinter\__init__.py", line 1639, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: invalid command name ".!label2"
最后,有没有办法把random.randint(0, b)的第二个参数改成入口和开头的按钮?
首先,当您将命令传递给按钮时,您需要将函数放在不带括号的位置:command=go
。如果您使用括号,该函数将在您声明按钮时调用,而不是在您按下按钮时调用。
其次,您不应在按下按钮后调用 root.mainloop()。你应该 运行 在文件末尾。
mainloop
永远不会 returns,所以在后面放置 sleep
和函数调用没有帮助。如果你想在主循环中 运行 编码,创建一个循环调用 tk.update()
和 tk.update_idletasks()
.
我认为更新的元素不需要再次打包更新。
最后,你为什么要从内部调用 go
?
from tkinter import *
import random
import time
root = Tk()
def getrandint():
result = random.randint(0, 100)
return result
def go():
lab2['text'] = 'Number: ' + str(getrandint())
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
#ent = Entry(root, width=20)
#number = ent.get()
b = Button(root, text='Go', command=go)
b.pack()
lab1.pack()
lab2.pack()
#ent.pack()
root.geometry('300x200')
root.mainloop()
让我们从基本错误开始,您对
mainloop()
的放置决定了所有小部件的显示内容(在编写良好的代码上)。在这种情况下,您想将mainloop()
放在末尾。在你的情况下,这甚至可以工作,因为你正在使用()
和具有包含mainloop()
功能的按钮(通过文字解释有点棘手:P)。接下来是,您不应该使用
()
为您的按钮调用该函数,因为它会自动启动该函数并且不会等待按下按钮:
b = Button(root, text='Go', command=go)
- 下一步是修复您的入口小部件和事件驱动编程。您不应该在代码开头接受用户的输入,因为它在开头是空的。您应该在触发事件(一个函数左右)后获取输入并将其存储在变量中,这意味着您的
getrandint()
将是:
def getrandint():
try: # To ignore if non integers are entered into the entry widget
result = random.randint(0, int(ent.get())) # Get the text from entry widget
return result
except TypeError: # Ignore the error
pass
- 接下来要避免使用
time.sleep()
,因为它会使 GUI 滞后。所以你应该改用root.after(ms,func)
,它将在指定的ms
: 之后调用
func
def go():
lab2['text'] = 'Number: ' + str(getrandint())
root.after(1000,go) # Repeat the function after 1 second
所以你的最终代码是:
from tkinter import *
import random
root = Tk()
root.geometry('300x200')
def getrandint():
try:
result = random.randint(0, int(ent.get()))
return result
except TypeError:
pass
def go():
lab2['text'] = 'Number: ' + str(getrandint())
root.after(1000,go)
lab1 = Label(root, text='Type in number')
lab2 = Label(root, text='Number:')
ent = Entry(root, width=20)
b = Button(root, text='Go', command=go)
b.pack()
lab1.pack()
lab2.pack()
ent.pack()
root.mainloop() # At the end of the code
另请注意:
您可以通过将 go()
更改为:
getrandint()
def go():
try: # If not an integer is entered into entry widget
lab2['text'] = 'Number: ' + str(random.randint(0,int(ent.get())))
root.after(1000,go)
except ValueError: # Ignore the error
pass
综上所述,您的错误是由于您的代码流动方式造成的。经常练习记住这些,你将永远不会再看到这些错误 ;)
根据您的说明编写的程序应如下所示(类似):
from tkinter import *
import random
import time
# Create function, which generates random number and update label
def set_random_num():
num = random.randint(0,100)
lab2.config(text=num)
# Initialize tkinter window
root = Tk()
# Create labels and button
lab1 = Label(root, text='Type in number')
lab1.pack()
lab2 = Label(root, text='Number:')
lab2.pack()
b = Button(root, text='Go', command=lambda: set_random_num())
b.pack()
# Keep it at the end of program
root.mainloop()
Lambda
函数允许您正确调用您的函数。我建议为 tkinter 寻找一些好的教程。试试 this.