简体   繁体   中英

Tkinter Label referring to variable doesn't update when variable changed

I have a problem with tkinter when a label refers to a value and I update the value by pressing a button. The value is indeed updated but the label text referring to this value is not.

How can I change this code that the button updates the value and the label refering to this value is updated and shown in the root ?

import tkinter

root = Tk()
root.title('Test Button')
root.geometry('600x450')


class Letter:
    def __init__(self, value):
        self.value = value


class Label:
    def __init__(self, master):
        self.a_label = tkinter.Label(root, text=current_letter.value)
        self.a_label.grid(row=2, column=1)

class Button:
    def __init__(self, master):

    self.Button1 = tkinter.Button(master, height = 12, width = 24,
                                  command= self.update_letter)
    self.Button1.grid(row=1, column=1)

    def update_letter(self):
        current_letter.value
        print("current_letter.value before: " + str(current_letter.value))
        current_letter.value += 1
        print("current_letter.value now: " + str(current_letter.value))
        root.update

#initialize a
a = Letter(0)
current_letter = a

b = Button(root)
l = Label(root)


root.mainloop()

Welcome to Stackoverflow. First of all, you don't really need to create seperate classes for label and button in your program. You can create them inside of main class as tkinter widgets. Then if you want to pass a variable of an instance of some class, you need to initiliaze it and pass to your update_letter function properly, which you can use lambda . Here is an example code that you can work on:

import tkinter as tk


class UpdateLabel:


  def __init__(self, master):
      self.master = master
      # Create instance of Letter class
      a = Letter(value=0)
      current_letter = a
      self.update_button = tk.Button(master, text='Update', command=lambda:self.update_letter(current_letter))
      self.update_button.grid(row=0, column=0)

      self.label = tk.Label(master, text='No Value')
      self.label.grid(row=1, column=0)

  def update_letter(self, current_letter):
      print("current_letter.value before: " + str(current_letter.value))
      current_letter.value += 1
      print("current_letter.value now: " + str(current_letter.value))
      self.label.configure(text='Value: {}'.format(current_letter.value))

class Letter:
     def __init__(self, value):
         self.value = value


if __name__ == '__main__':
    root = tk.Tk()
    app = UpdateLabel(master=root)
    root.mainloop()

In that link How to change label text , you can find other options for changing a text in tkinter label widget. I hope it helps

My, what a big button you have.

If you use a tkinter Variable , then updating it will automatically change what's in any widgets that refers to one of them. Here's some documentation describing them, and here's some more describing how to use them.

Here's how that could be done to the code in your question:

import tkinter

root = tkinter.Tk()
root.title('Test Button')
root.geometry('600x450')


class Letter:
    def __init__(self, value):
        self.value = tkinter.IntVar(value=value)  # Store in a tkinter Variable.


class Label:
    def __init__(self, master, letter):
        self.a_label = tkinter.Label(master, textvariable=letter.value)
        self.a_label.grid(row=2, column=1)


class Button:
    def __init__(self, master, letter):
        self.letter = letter
        self.Button1 = tkinter.Button(master, height=12, width=24,
                                      command=self.update_letter)
        self.Button1.grid(row=1, column=1)

    def update_letter(self):
        current_value = self.letter.value.get()
        print("letter.value before: " + str(current_value))
        self.letter.value.set(self.letter.value.get() + 1)
        print("letter.value now: " + str(self.letter.value.get()))


# initialize a
a = Letter(0)

b = Button(root, a)
l = Label(root, a)

root.mainloop()

A comment: I found having your own classes named the same as those in tkinter a bit confusing because, while they superficially seem similar, they are actually very different—which could lead to difficult-to-understand programming errors.

It is because you did not update the label l after you have updated current_letter . The simple solution is to change current_letter to IntVar and update class Label and Button as below:

class MyLabel:
    def __init__(self, master):
        self.a_label = tkinter.Label(root, textvariable=current_letter)
        self.a_label.grid(row=2, column=1)

class MyButton:
    def __init__(self, master):
        self.Button1 = tkinter.Button(master, height = 12, width = 24,
                                      command= self.update_letter)
        self.Button1.grid(row=1, column=1)

    def update_letter(self):
        value = current_letter.get()
        print("current_letter.value before: ", value)
        value += 1
        print("current_letter.value now: ", value)
        current_letter.set(value)

current_letter = tkinter.IntVar(0)

b = MyButton(root)
l = MyLabel(root)

Note that I have removed class Letter as it is not necessary. I also rename class Label and Button to MyLabel and MyButton respectively as they are classes in tkinter.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM