Tk label widget not refreshing - python-3.x

from tkinter import*
hp = 10
def inc():
global hp
hp+=2
mainloop()
def dec():
global hp
hp-=2
mainloop()
master=Tk()
w = Label(master, text="Health = " + str(hp))
bu = Button(master, text="Increase", command=inc)
bd = Button(master, text="Decrease", command=dec)
bu.pack()
bd.pack()
w.pack()
while True:
mainloop()
I want the label that displays the integer variable 'hp' to update when I click the button widget that changes its value. Why isn't it refreshing? If I put the definition bits below the tk bit, I know i'll get an error saying that the buttons' commands don't exist!

For one, you must call mainloop() exactly once, and definitely not in an infinite loop.
For another, labels don't just magically update. You have to use the config method to change the string that is displayed in a label widget.

The function mainloop() is itself a loop (the clue is in the name) so you don't call it in an infinite while loop. This will fix part of your problem.
Also, you need to use w.config(text="somenewlabeltext") inorder to change the text as when you originally create the label, the text is set and even when you change hp, the string does not change as you have found.
Your final code may look something like this:
from tkinter import *
hp = 10
def inc():
global hp, w
hp+=2
w.config(text="Health = " + str(hp))
def dec():
global hp, w
hp-=2
w.config(text="Health = " + str(hp))
master=Tk()
w = Label(master, text="Health = " + str(hp))
w.pack()
bu = Button(master, text="Increase", command=inc)
bu.pack()
bd = Button(master, text="Decrease", command=dec)
bd.pack()
mainloop()

Related

How to make a variable equal to the input received from the input field in tkinter?

I was wondering how to make this code work.I always get 12 in the console.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
e.get = s
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
root.mainloop()
You have to change the function clicked as follows:
def clicked():
s=e.get()
print(s)
There were two errors in your code:
You were trying to assign the value 12 to a function.
You were not calling the function (using parenthesis).
this line here:
e.get = s
says the method of e named get is equally to s.
Which is nonsense. You want s to be equally to what is returned by e.get.
to have something returned you need to invoke this method first.
So the logical right way to do this is by:
s = e.get()
Note that it is a variable in the enclosed namespaces of your function.
To make it global you need to global the variable.
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.pack()
def clicked():
#global s
s = e.get()
print(s)
button = Button(root,command=clicked,text="ok")
button.pack()
b2 = Button(root, text='print', command=lambda:print(s))
b2.pack()
root.mainloop()
I have used .place() instead of .pack() and placed my same entry on the same position as it was place before, but this time if value changes as you click on button OK.
Use e.insert(0,"Value") to insert any value in a entry.
This worked for me. Also let me know did it worked for you as well?
from tkinter import *
s = 12
root = Tk()
root.geometry("200x200")
root.title("Program")
e = Entry(root)
e.place(relx=0.1, rely = 0.1)
def clicked():
e = Entry(root)
e.insert(0, s)
e.place(relx=0.1, rely = 0.1)
button = Button(root,command=clicked,text="ok")
button.place(relx=0.4, rely = 0.2)
root.mainloop()

How to make a label cycle through preset words or phrases when a button is pressed in tkinter

So I'm trying to make it cycle through each letter of the alphabet when the button is clicked.
I have tried the method i am showing now.
I have also tried many others and i couldn't get anything to work.
If you do have a solution please try keep it simple i am kinda new too this.
from tkinter import *
win = Tk()
win.title('ab')
a = 0
def changetext():
a = a+1
if a == 1:
lbl.config(text='b')
def changetext():
if a == 2:
lbl.config(text='c')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()```
In python, variables inside functions are local, which means that if you define a variable a = 0 outside the function, then do a = 1 in the function, the a equals 1 inside the function but it still equals 0 outside. If you want to change the value of a outside the function from inside the function, you need to declare a as a global variable (see code below).
import tkinter as tk # avoid import * to because it leads to naming conflicts
win = tk.Tk()
win.title('ab')
i = 0
letters = "abcdefghijklmnopqrstuvwxyz"
def changetext():
global i # change value of i outside function as well
i += 1
i %= 26 # cycle through the alphabet
lbl.configure(text=letters[i])
lbl = tk.Label(win, text='a')
lbl.grid(row=1, column=1)
btn = tk.Button(win,text='u', command=changetext)
btn.grid(row=2, column=1)
win.mainloop()
You can use itertools.cycle to create a cycle list and then use next() function to get the next item in the cycle list:
import tkinter as tk
from itertools import cycle
words = cycle(['hello', 'world', 'python', 'is', 'awesome'])
root = tk.Tk()
lbl = tk.Label(root, text=next(words), width=20)
lbl.pack()
tk.Button(root, text='Next', command=lambda: lbl.config(text=next(words))).pack()
root.mainloop()
I actually used the first method and adapted it by making the variable global because then it will update it for all the functions making my first method work
from tkinter import *
win = Tk()
win.title('ab')
i = 0
def changetext():
global i
i = i + 1
if i == 1:
lbl.config(text='word 2')
if i == 2:
lbl.config(text='word 1 ')
lbl = Label(win,text='a')
lbl.grid(row=1,column=1)
btn = Button(win,text='u', command =changetext)
btn.grid(row=2,column=1)
win.mainloop()

Returning a value from a tkinter form

I'm using code where I need to ask the user for input, using a tkinter window (I'm not using tkinter in other parts of the code).
My issue is that I simply need to use the tkinter window to return a value upon pressing the OK button on the form, which will also close down the form. The only way I can get it to work so far is by using a global variable. I've searched for other solutions to this but either they don't return a value (they simply print it) or don't allow passing text for the prompt.
Thanks in advance if you can help with this.
from tkinter import *
def input_text(prompt):
def ok():
global ret
ret = entry.get()
master.destroy()
master = Tk()
lbl = Label(master, text=prompt)
lbl.pack()
entry = Entry(master)
entry.pack()
entry.focus_set()
butt = Button(master, text = "OK", width = 10, command = ok)
butt.pack()
mainloop()
print("I am here!")
ret=""
input_text("Enter something")
print("ret is:", ret)
After a good night's sleep I've solved the problem :-)
The solution was to create a class and return the response via an attribute. Here's the code for the archive ... just in case anyone out there has a similar question.
from tkinter import *
class InputForm():
def __init__ (self, prompt):
self.prompt = prompt
self.response = ""
def ok():
self.response = entry.get()
master.destroy()
master = Tk()
lbl = Label(master, text=self.prompt)
lbl.pack()
entry = Entry(master)
entry.pack()
entry.focus_set()
butt = Button(master, text = "OK", width = 10, command = ok)
butt.pack()
mainloop()
abc = InputForm("Enter something").response
print("returned value is:", abc)

Python 3 Radio button controlling label text

I am in the process of learning Python3 and more of a necessity, the TkInter GUI side. I was working my way through a book by James Kelly, when I encountered this problem. All his examples made a new window with just label/canvas/check box etc which seemed to work OK.
But as I wanted to experiment in a more real world scenario I put most things on one window. This where I encountered my problem. I can not get the radio button in the frame to alter the wording of a label in the parent window.
Complete code is:-
#! /usr/bin/python3
from tkinter import *
def win_pos(WL,WH,xo=0,yo=0) :
# Screen size & position procedure
# Screen size
SW = home.winfo_screenwidth()
SH = home.winfo_screenheight()
# 1/2 screen size
sw=SW/2
sh=SH/2
# 1/2 window size
wl=WL/2
wh=WH/2
# Window position
WPx=sw-wl+xo
WPy=sh-wh+yo
# Resulting string
screen_geometry=str(WL) + "x" + str(WH) + "+" + str(int(WPx)) + "+" \ + str(int(WPy))
return screen_geometry
# Create a window
home=Tk()
home.title("Radio buttons test")
# Set the main window
home.geometry(win_pos(600,150))
lab1=Label(home)
lab1.grid(row=1,column=1)
fraym1=LabelFrame(home, bd=5, bg="red",relief=SUNKEN, text="Label frame text")
fraym1.grid(row=2,column=2)
laybl1=Label(fraym1, text="This is laybl1")
laybl1.grid(row=0, column=3)
var1=IntVar()
R1=Radiobutton(fraym1, text="Apple", variable=var1, value=1)
R1.grid(row=1, column=1)
R2=Radiobutton(fraym1, text="Asus", variable=var1, value=2)
R2.grid(row=1, column=2)
R3=Radiobutton(fraym1, text="HP", variable=var1, value=3)
R3.grid(row=1, column=3)
R4=Radiobutton(fraym1, text="Lenovo", variable=var1, value=4)
R4.grid(row=1, column=4)
R5=Radiobutton(fraym1, text="Toshiba", variable=var1, value=5)
R5.grid(row=1, column=5)
# Create function used later
def sel(var) :
selection="Manufacturer: "
if var.get() > 0 :
selection=selection + str(var.get())
lab1.config(text=selection)
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
mainloop()
I realise that there is room for improvement using classes/functions but I need to get this resolved in my head before I move on. As it can be hopefully seen, I'm not a complete novice to programming, but this is doing my head in.
Can a solution, and reasoning behind the solution, be given?
You can modify your label's text by assigning the same variable class object, var1 as its textvariable option as well but since lab1's text is slightly different, try removing:
R1.config(command=sel(var1))
R2.config(command=sel(var1))
R3.config(command=sel(var1))
R4.config(command=sel(var1))
R5.config(command=sel(var1))
R1.select()
and modify sel to:
def sel(*args) :
selection="Manufacturer: "
selection=selection + str(var1.get())
lab1.config(text=selection)
and then call var1.trace("w", sel) somewhere before mainloop as in:
...
var1.trace("w", sel)
mainloop()
Also for a simple example:
import tkinter as tk
root = tk.Tk()
manufacturers = ["man1", "man2", "man3", "man4", "man5"]
lbl = tk.Label(root, text="Please select a manufacturer.")
lbl.pack()
# create an empty dictionary to fill with Radiobutton widgets
man_select = dict()
# create a variable class to be manipulated by radiobuttons
man_var = tk.StringVar(value="type_default_value_here_if_wanted")
# fill radiobutton dictionary with keys from manufacturers list with Radiobutton
# values assigned to corresponding manufacturer name
for man in manufacturers:
man_select[man] = tk.Radiobutton(root, text=man, variable=man_var, value=man)
#display
man_select[man].pack()
def lbl_update(*args):
selection="Manufacturer: "
selection=selection + man_var.get()
lbl['text'] = selection
#run lbl_update function every time man_var's value changes
man_var.trace('w', lbl_update)
root.mainloop()
Example with label's identical to that of radiobutton's value:
import tkinter as tk
root = tk.Tk()
# radiobutton group will the button selected with the value=1
num = tk.IntVar(value=1)
lbl = tk.Label(root, textvariable=num)
zero = tk.Radiobutton(root, text="Zero", variable=num, value=0)
one = tk.Radiobutton(root, text="One", variable=num, value=1)
#display
lbl.pack()
zero.pack()
one.pack()
root.mainloop()

How do I make a button console using Tkinter?

I have got a script wiht nine diferent options in a text menu. I would like to change the menu for a GUI using tkinter.
The menu has nine options which are a bucle if, elif... esle from 1 to 9. The last one is the 'exit' one.
How do I transform the menu if, elif, elif....else in a window with nine buttons each one for a different option and run the same script ?
I am trying the following code:
from tkinter import*
ventana = Tk()
variable = ''
def opcion1():
global variable
variable = '1'def opcion2 ():
global variable
variable = '2'
root = Tk()
boton1 = Button(ventana, text='OPCION1',command=opcion1)
boton1.pack()
boton2 = Button(ventana, text='OPCION2',command=opcion2)
boton2.pack()
botonSalir = Button(ventana, text='EXIT',command=quit)
botonSalir.pack()
root.mainloop()
How can I do that?
Hopefully this helps!
from Tkinter import *
root = Tk()
def f1():
print('f1')
def f2():
print('f2')
def f3():
print('f3')
MODES = [("Option1", f1, '1'), ("Option2", f2, '2'), ("Option3", f3, '3')]
v = StringVar()
v.set("L") # initialize
for text, function, mode in MODES:
b = Radiobutton(root, text=text, indicatoron=0, variable=v, command=function, value=mode)
b.pack(anchor=W)
root.mainloop()

Resources