Home > Net >  Tkinter - How to increase label value by clicking button?
Tkinter - How to increase label value by clicking button?

Time:06-08

By clicking the Start button, the value on label must be increased by 3 every 500 milliseconds until I destroy the window, but the value is stuck on 0.

from tkinter import *

def start(value):
    value =3
    label['text']=str(value)
    if True:
        root.after(500, start, value)
def stop():
    root.destroy()

root = Tk()
root.geometry("420x250")
value = 0

label = Label(root, background="pink", width=20, height=2, text = str(value))
label.pack(anchor=W, pady=5)
btn1 = Button(root, text="Start", width=6, height=2, command=start).pack(
            side=LEFT, anchor=NW, padx=2, pady=2)
btn2 = Button(root, text="Stop", width=6, height=2, command=stop).pack(
            side=LEFT, anchor=NW, pady=2)

root.mainloop()

CodePudding user response:

The reason your code doesn't work is because the command=start for the Start button isn't passing it the parameter the start() function expects. That could be fixed by removing the parameter from the function's definition and modifying it to directly access the global variable.

However I think it would be better in this case to use a tkinter's "Variable Classes" to do things given what else it looks like what you're trying to do. (See The Variable Classes (BooleanVar, DoubleVar, IntVar, StringVar) for a little documentation.) One of the most useful features they have is that they can be used in many widgets (such as Labels) instead of supplying a static text string. When that's done, the widget's display of the variable's value will automatically get update itself whenever the value of tkinter.Variable changes.

Below is example code showing how to use them which also makes use of an additional tkinter.Variable to hold the value of a boolean flag the controls whether the updating is enabled. I also added a third Button to quit since I changed what the Stop button does in your code.

from tkinter import *

def start():
    incflag_var.set(True)
    inc_value()  # Start incrementing.

def inc_value():
    value_var.set(value_var.get()   3)  # Will auto update label.

    if incflag_var.get():
        root.after(500, inc_value)

def stop():
    incflag_var.set(False)


root = Tk()
root.geometry("420x250")

value_var = IntVar(value=0)
incflag_var = BooleanVar(value=False)

label = Label(root, background="pink", width=20, height=2, textvariable=value_var)
label.pack(anchor=W, pady=5)
Button(root, text="Start", width=6, height=2, command=start).pack(
            side=LEFT, anchor=NW, padx=2, pady=2)
Button(root, text="Stop", width=6, height=2, command=stop).pack(
            side=LEFT, anchor=NW, pady=2)
Button(root, text="Quit", width=6, height=2, command=root.quit).pack(
            side=LEFT, anchor=NW, pady=2)

root.mainloop()

CodePudding user response:

As it turns out tkinter.Label can support integer values too, so the way you can do incrementing is by simply using label["text"] = 3 if the starting text of the label is an integer (or float probably works too).

You also need to not let it create multiple after "loops" so setting some flags and checking those also should be added, the way I implemented it is by creating an attribute for that same label that tells whether it has started counting and if it hasn't then start.

import tkinter as tk


def start():
    if not getattr(label, "counting", False):
        update()
    label.counting = True


def stop():
    root.destroy()


def update():
    label["text"]  = 3
    root.after(500, update)


root = tk.Tk()
root.geometry("420x250")

label = tk.Label(root, background="pink", width=20, height=2, text=0)
label.pack(anchor="w", pady=5)
tk.Button(root, text="Start", width=6, height=2, command=start).pack(
    side="left", anchor="nw", padx=2, pady=2
)
tk.Button(root, text="Stop", width=6, height=2, command=stop).pack(
    side="left", anchor="nw", pady=2
)

root.mainloop()

Also note that there is no point in assigning the returned values of pack (or grid or place) to a variable, you can just simply create buttons without those variables, label on the other hand of course needs to be referenced so it's properly made for that.

Also:
I strongly advise against using wildcard (*) when importing something, You should either import what You need, e.g. from module import Class1, func_1, var_2 and so on or import the whole module: import module then You can also use an alias: import module as md or sth like that, the point is that don't import everything unless You actually know what You are doing; name clashes are the issue.

  • Related