更新 tkinter 标签并使用 entry 来选择参数

问题描述

我做了一个小脚本来练习tkinter的使用。我希望程序打开一个窗口并显示一个标签。按下按钮后,标签显示 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()

这就是我得到的程度。它打开一个窗口并显示一个随机数,但不刷新该数字。按钮甚至没有显示。此外,当我关闭窗口时,Python 3.8 会显示以下错误消息:

Traceback (most recent call last):
  File "C:/Users/chris/Desktop/WeatherLinkPy/testing.py",line 102,in <module>
    b = Button(root,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)的第二个参数?

解决方法

  • 让我们从基本错误开始,您对 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),它会在指定的 func 之后调用 ms
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,command=go)

b.pack()
lab1.pack()
lab2.pack()
ent.pack()

root.mainloop() # At the end of the code

另请注意:

您可以通过将您的 getrandint() 更改为:

来完全摆脱您的 go()
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

话虽如此,您的错误发生是由于您的代码流动方式。多练习牢记这些,你将永远不会再看到这些错误;)

,

首先,当你向按钮传递一个命令时,你需要把函数放在不带括号的地方:command=go。如果使用括号,则该函数将在声明按钮时调用,而不是在按下按钮时调用。

其次,您不应该在按下按钮后调用 root.mainloop()。您应该在文件末尾运行它。

mainloop 永远不会返回,因此将 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='Number:')
#ent = Entry(root,width=20)
#number = ent.get()
b = Button(root,command=go)

b.pack()
lab1.pack()
lab2.pack()
#ent.pack()

root.geometry('300x200')
root.mainloop()
,

根据您的指令编写的程序应如下所示(类似):

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,command=lambda: set_random_num()) 
b.pack()

# Keep it at the end of program
root.mainloop() 

Lambda 函数允许您正确调用您的函数。我建议为 tkinter 寻找一些好的教程。试试this

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...