Python 3 Radio button controlling label text - python-3.x

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()

Related

Updating imagef on TK buttons, each time a button is pressed

I try to build a short of captha app that must run on desktop and emulated on Android, so far I have success with the example "simple calculator" that use TK and Buttons.
I success to load the first row of pictures inside the buttons, but as soon as I try to update the images, buttons disapear
here my code (resumed for two buttons, but same the same)
#!/usr/bin/env python3
# Python program to create a simple GUI
# calculator using Tkinter
from tkinter import *
import os
from PIL import ImageTk,Image, ImageFilter, ImageFont , ImageDraw , ImageOps, ImageFile
# checkea que el script corre en display0, si no, configura el output grafico a este
if os.environ.get('DISPLAY','') == '':
os.environ.__setitem__('DISPLAY', ':0.0')
# globally declare the ThisInstanceImages variable
ThisInstanceImages = []
# Function to update each button is pressed
def press(num):
reloadImages()
def reloadImages():
global ThisInstanceImages
...
aux_IMG = actualImage.crop((10,10,110,110)).resize((250,250))
if len(ThisInstanceImages) == 0:
ThisInstanceImages.append(ImageTk.PhotoImage(aux_IMG))
else:
ThisInstanceImages[0] = ImageTk.PhotoImage(aux_IMG)
aux_IMG = actualImage.crop((110,110,210,210)).resize((250,250))
if len(ThisInstanceImages) == 1:
ThisInstanceImages.append(ImageTk.PhotoImage(aux_IMG))
else:
ThisInstanceImages[1] = ImageTk.PhotoImage(aux_IMG)
# Driver code
if __name__ == "__main__":
# create a GUI window
gui = Tk()
# set the background colour of GUI window
gui.configure(background="light green")
# set the title of GUI window
gui.title("Simple Calculator")
# set the configuration of GUI window
gui.geometry("640x480")
## fisrt run - aux
reloadImages()
# create a Buttons and place at a particular
# location inside the root window .
# when user press the button, the command or
# function affiliated to that button is executed .
button1 = Button(gui, text='', image = ThisInstanceImages[0], fg='black', bg='black',
command=lambda: press(1), height=250, width=250, borderwidth=0)
button1.grid(row=2, column=0)
button2 = Button(gui, text=' 2 ', image = ThisInstanceImages[1], fg='black', bg='black',
command=lambda: press(2), height=250, width=250, borderwidth=0)
button2.grid(row=2, column=1)
...
# start the GUI
gui.mainloop()
the first call [on ## fisrt run - aux] works ok, but as soon as button is pressed, and jump for second time on reloadImages() and hit the seventh line (ThisInstanceImages[0] = ImageTk.PhotoImage(aux_IMG)) app buttons disapear. I try with a little trick to do not delete any image, (really change), same result
here the trick:
def reloadImages():
global ThisInstanceImages
...
aux_IMG = actualImage.crop((10,10,110,110)).resize((250,250))
ThisInstanceImages.append(ImageTk.PhotoImage(aux_IMG))
aux_IMG = actualImage.crop((110,110,210,210)).resize((250,250))
ThisInstanceImages.append(ImageTk.PhotoImage(aux_IMG))
if len(ThisInstanceImages) > 2:
ThisInstanceImages[0] = ThisInstanceImages[2]
is that achivable ??

how to get a button name as a value in python

using tkinter i created buttons from a list and what I want to have is when I click on the button to have a lable that say HDD (the button name ) is added
for examble if I clicked on the button /dev/sda
I should have HDD /dev/sda is added
but the problem is that I always get the last list value in my list
if I click on the button that have this name /dev/sda I get HDD /dev/sdb is
added
thanx in advanced
HDD=[/dev/sda,/dev/sdb,/dev/sdc]
top = tkinter.Tk()
top.geometry("500x500")
def hdd():
hdd = tkinter.Tk()
hdd.geometry("500x500")
len(HDD)
for i in range(0 , len(HDD)):
i = HDD[i]
def addtolist():
hlist =[]
hlist.append(i)
lable = Label(hdd, text="HDD {} is added to the
zpool".format(i))
lable.pack()
print(i)
bb = Button(hdd, text=str(i), command=addtolist)
bb.grid(row=1, column=1)
bb.pack()
e = Button(top, text = "HDD", command = hdd)
e.grid(row=0, column=5)
I'm not sure what you mean with "i created buttons from a list"
from tkinter import *
top = Tk()
top.geometry("500x500")
button_names = ["dev/sda", "dev/sdb"]
button_list = [] # for later needs
#my understanding of creating buttons from a list!?
for i in button_names:
button = Button(top, text=i, command=lambda x=i:lable_name(x))
button.pack()
button_list.append(button)
#Labels are packed bellow because I don't know where you want to pack it
def lable_name(name):
label = Label(top, text="HDD {} is added to the zpool".format(name))
label.pack()
top.mainloop()
Also weird is that line *hdd = tkinter.Tk()" and then you're trying to use len() on it.

Tkinter : Recording entries dynamically created by buttons

I'm trying to allow the user to enter as many strings as he wants by clicking some sort of '+' button, and keep the strings in a list. (He enters a first string, clicks '+', another entry box appears, etc.)
For the moment, here's what I've got:
def addEntry(window, r, e):
if r < 9:
global entries
entries.append(e.get())
r += 1
e = tk.Entry(window)
e.grid(column=1, row=r)
add = tk.Button(window, text=' + ', command=lambda:addEntry(window, r, e))
add.grid(column=2, row=r, sticky=tk.W)
else:
errmsg = 'Max. 10 items'
tk.Label(window, text=errmsg).grid(column=1, row=r+1)
import tkinter as tk
global entries # the main list of strings
entries = []
r = 0 # index for rows ; will not be 0 in the final code as there will be other widgets
win = tk.Tk()
e = tk.Entry(win)
e.grid(column=1, row=r)
add = tk.Button(win, text=' + ', command=lambda:addEntry(win, r, e))
add.grid(column=2, row=r, sticky=tk.W)
win.mainloop()
This isn't elegant, and the last entry is not recorded.
I've tried making entries a list of Entry() items (not e.get() items), but then I can't access the strings (TclError: invalid command name ".!entry4"). I've tried emulating this, which led me to make entries a global variable ; I've tried using this, but I don't fully understand the first answer, and as far as I can tell the strings aren't recorded ; I've tried adapting the class defined in the second answer, but I wasn't able to add buttons dynamically. (I like the idea of making a class, though.) I feel like I should be able to do this, but after a wasting a day on it, might as well ask for help.
Don't put the value in a list, put the actual widget. You should only call the get method when you actually need the values.
Also, I strongly recommend you put the entries in a dedicated frame. That way you don't have to worry about what other widgets might be in the window, and you don't have to juggle row and column numbers. Put them in a frame and use pack since they are stacked top-to-bottom and all share the same size.
Example:
import tkinter as tk
def addEntry(window):
global entries
if len(entries) > 10:
error_message.configure(text="Max. 10 items")
else:
error_message.configure(text="")
entry = tk.Entry(window)
entry.pack(side="top", fill="x")
entries.append(entry)
def show():
for entry in entries:
print("=>", entry.get())
entries = []
win = tk.Tk()
entry_frame = tk.Frame(win)
error_message = tk.Label(win)
error_message.grid(row=1, column=0, sticky="nsew")
add = tk.Button(win, text=' + ', command=lambda: addEntry(entry_frame))
show = tk.Button(win, text="Show values", command=show)
add.grid(row=0, column=1, sticky=tk.NW)
show.grid(row=0, column=2, sticky=tk.NW)
entry_frame.grid(row=0, column=0, sticky="nsew")
# create the first entry automatically
addEntry(entry_frame)
win.mainloop()

Tk label widget not refreshing

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()

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