【问题标题】:Update tkinter label and use entry to choose parameter更新 tkinter 标签并使用 entry 来选择参数
【发布时间】:2021-01-04 13:50:42
【问题描述】:

我做了一个小脚本来练习使用 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, 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 而不是command=go()。另外,你应该在最后运行 root.mainloop()。
  • 这里有很多错误,建议你先上tkinter的教程。
  • 也代替sleep 我建议after 方法

标签: python python-3.x tkinter tkinter-label


【解决方案1】:
  • 让我们从基本错误开始,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

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

【讨论】:

    【解决方案2】:

    首先,当您将命令传递给按钮时,您需要将不带括号的函数放入: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='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()
    

    【讨论】:

      【解决方案3】:

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

      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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-12-20
        • 1970-01-01
        • 2017-04-12
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多