Tkinter. StringVar(). How I can update the Label in my code. - python

I have a problem with updating the Label widget (lab1_datum_in).
I would like to change the Label text every time I change radiobuttons.
Really do not know what is wrong.
Could anyone help?
My interpreter is Python 3.4
Thanks in advance!
import tkinter
root = tkinter.Tk()
# Creating radiobuttons
v = tkinter.IntVar()
v.set(1) # initializing the choice
transformation_types = [
("WGS84 --> ED50(North of 62N)",1),
("WGS84 --> ED50(South of 62N)",2),
("ED50(North of 62N) --> WGS84",3),
("ED50(South of 62N) --> WGS84",4),
]
datum_in_text = tkinter.StringVar()
datum_in_text.set('WGS84')
def ChangeDatumText():
if v.get() == 1:
global datum_in_text
datum_in_text.set('WGS84')
elif v.get() == 2:
global datum_in_text
datum_in_text.set('WGS84')
elif v.get() == 3:
global datum_in_text
datum_in_text.set('ED50(North of 62N')
elif v.get() == 4:
global datum_in_text
datum_in_text.set('ED50(North of 62N')
for txt, val in transformation_types:
tkinter.Radiobutton(root,
text=txt,
padx=20,
variable=v,
command=ChangeDatumText,
value=val).grid()
lab1_datum_in = tkinter.Label(root, text=datum_in_text.get()).grid(row=9, column=1)
root.mainloop()

As #jonrsharpe indicated in a comment, to slave the text displayed on the Label widget you need to set the textvariable option to a control variable of class StringVar, which in your case is datum_in_text. The text option you have is for displaying a one or more lines of static text.
This means you need to use:
lab1_datum_in = tkinter.Label(
root, textvariable=datum_in_text).grid(row=9, column=1)
instead of what you have.
BTW, all those global datum_in_text declarations you have in the ChangeDatumText() function are unnecessary and all but the first produce non-fatal syntax warnings when they're encountered. Since you're only calling one of the global variable's methods, rather than assigning a value to the variable name itself, you don't even need do this, but if you do put one in—it doesn't hurt—just declare it global once at the very beginning of the function.
Another thing to be aware of is that the variable lab1_datum_in will be set ti None by the assignment because the grid() method doesn't return anything — so you should split it up into two separate steps.

Related

Tkinter widget where User chooses parameter values, but how do I store these values?

My objective is to create three variables called 'Number of pipes','Anisotropy ratio', 'Filter depth (in cm)' which values are chosen by the user (through a User interface). I achieved to create the scrollbar of Tkinter and to enter values but these are not stored as variables. Could someone give me a hand solving that? I am new in Python and specially I am struggling with Tkinter. The code is developped in Python 3.7:
root = tk.Tk()
root.geometry('1000x1000')
#Description show in window
info=tk.Label(root,anchor='e')
info.pack()
#Parameters
parameters = ('Number of pipes','Anisotropy ratio', 'Filter depth (in cm)')
def ask_parameter(entry):
user_pipes = str (entry['Number of pipes'].get())
user_aniso = str (entry['Anisotropy ratio'].get()) #effective screen length = b
user_depth = str (entry['Filter depth (in cm)'].get())
print(user_pipes,user_aniso,user_depth)
#if parameters
# return True
# else:
# tkinter.messagebox.showwarning ('Only numbers', 'Try again')
# return True
#
def form(parameters):
entry = {}
for parameter in parameters:
print(parameter)
row = tk.Frame(root)
lab = tk.Label(row, width=15, text=parameter+": ", anchor='w')
ent = tk.Entry(row)
row.pack(side=tk.TOP,
fill=tk.X,
padx=2,
pady=2)
lab.pack(side=tk.LEFT)
ent.pack(side=tk.RIGHT, expand=tk.YES,fill=tk.X)
entry[parameter] = ent
return entry
if __name__ == '__main__':
ents = form(parameters)
save_button = tk.Button(root)
save_button.configure(text='Save', command=lambda: ask_parameter(ents))
save_button.pack()
root.mainloop()
Any problem is shown with the code but the parameters are not stored as variables with the entered values.
Thank you very much for your time.
Your code is storing the values inputted through the GUI to variables, your problem is probably that your variables aren't global, so you won't be able to use them outside of the function they are created in. you can either get around this with a return, or make them global by putting global varname above the definition of each variable as well as at the start of every function that will use it.

Tkinter - Creating multiple check boxes using a loop

I am trying to create a program that allows the user to select any number of check boxes and hit a button to return a random result from those check boxes. Since I am basing my list off the roster of Smash bros ultimate, I am trying to avoid creating 70+ variables just to place check boxes. However, I am unable to figure out how to iterate this. The various values set for rows are just placeholders until I can figure this out. I would also like to have a reset button at the top that allows the user to automatically uncheck every box. This code is what I have so far. Any help would be greatly appreciated.
#!/usr/bin/python3
from tkinter import *
window = Tk()
#window name and header
window.title("Custom Random SSBU")
lbl = Label(window, text="Select the fighters you would like to include:")
lbl.grid(column=1, row=0)
f = [] #check boxes
ft = open("Fighters.txt").readlines() #list of all the character names
fv=[0]*78 #list for tracking what boxes are checked
ff=[] #list to place final character strings
def reset():
for i in fv:
fv[i]=0
rst = Button(window, text="Reset", command=reset)
rst.grid(column=0, row=3)
for y in range (0,77):
f[y] = Checkbutton(window, text = ft[y], variable = fv[y])
f[y].grid(column=0, row=4+y)
def done():
for j in fv:
if fv[j] == 1:
ff.append(fv[j])
result = random.choice(ff)
r=Label(window, text=result)
d = Button(window, text="Done", command=done)
d.grid(column=0, row = 80)
window.mainloop()
Unfortunately I'm afraid you are going to have to create variables for each checkbox.
tkinter has special purpose Variable Classes for holding different types of values, and if you specify an instance of one as the variable= option when you create widgets like Checkbutton, it will automatically set or reset its value whenever the user changes it, so all your program has to do is check its current value by calling its get() method.
Here's an example of the modifications to your code needed to create them in a loop (and use them in the done() callback function):
import random
from tkinter import *
window = Tk()
#window name and header
window.title("Custom Random SSBU")
lbl = Label(window, text="Select the fighters you would like to include:")
lbl.grid(column=1, row=0)
with open("Fighters.txt") as fighters:
ft = fighters.read().splitlines() # List of all the character names.
fv = [BooleanVar(value=False) for _ in ft] # List to track which boxes are checked.
ff = [] # List to place final character strings.
def reset():
for var in fv:
var.set(False)
rst = Button(window, text="Reset", command=reset)
rst.grid(column=0, row=3)
for i, (name, var) in enumerate(zip(ft, fv)):
chk_btn = Checkbutton(window, text=name, variable=var)
chk_btn.grid(column=0, row=i+4, sticky=W)
def done():
global ff
ff = [name for name, var in zip(ft, fv) if var.get()] # List of checked names.
# Randomly select one of them.
choice.configure(text=random.choice(ff) if ff else "None")
d = Button(window, text="Done", command=done)
d.grid(column=0, row=len(ft)+4)
choice = Label(window, text="None")
choice.grid(column=1, row=3)
window.mainloop()
I wasn't sure where you wanted the Label containing the result to go, so I just put it to the right of the Reset button.
variable = fv[y]
This looks up the value of fv[y] - i.e, the integer 0 - at the time the Checkbutton is created, and uses that for the variable argument.
You need to use an instance of one of the value-tracking classes provided by TKinter, instead. In this case we want BooleanVar since we are tracking a boolean state. We can still create these in a list ahead of time:
text = open("Fighters.txt").readlines()
# Let's not hard-code the number of lines - we'll find it out automatically,
# and just make one for each line.
trackers = [BooleanVar() for line in text]
# And we'll iterate over those pair-wise to make the buttons:
buttons = [
Checkbutton(window, text = line, variable = tracker)
for line, tracker in zip(text, trackers)
]
(but we can not do, for example trackers = [BooleanVar()] * len(text), because that gives us the same tracker 78 times, and thus every checkbox will share that tracker; we need to track each separately.)
When you click the checkbox, TKinter will automatically update the internal state of the corresponding BooleanVar(), which we can check using its .get() method. Also, when we set up our options for random.choice, we want to choose the corresponding text for the button, not the tracker. We can do this with the zip trick again.
So we want something more like:
result_label = Label(window) # create it ahead of time
def done():
result_label.text = random.choice(
label
for label, tracker in zip(text, trackers)
if tracker.get()
)

How do I create a button in Python Tkinter to increase integer variable by 1 and display that variable?

I am trying to create a Tkinter program that will store an int variable, and increase that int variable by 1 each time I click a button, and then display the variable so I can see that it starts out as 0, and then each time I click the button it goes up by 1. I am using python 3.4.
import sys
import math
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("My Button Increaser")
counter = 0
def nClick():
counter + 1
def main_click():
mLabel = Label(root, text = nClick).pack()
mButton1 = Button(text = "Increase", command = main_click, fg = "dark green", bg = "white").pack()
root.mainloop()
Ok so there are a few things wrong with your code so far. My answer basically changes what you have already into the easiest way for it to do what you want.
Firstly you import libraries that you don't need/use (you may need them in your whole code, but for this question include a minimal example only). Next you must deifne the counter variable as a global variable, so that it will be the same in the function (do this inside the function as well). Also you must change counter + 1 to counter += 1 so it increments the variable
Now the code will be able to count, but you have set variables as Buttons, but then made them None type objects, to change this .pack() the variable on the next line. You can get rid of the second function as you only need one, then you change the command of the button and its text to counter. Now to update the text in the button, you use .config(text = counter) which configures the button.
Here is the final solution (changes button value and has no label, but this is easily changed):
from tkinter import *
root = Tk()
root.geometry("200x200")
root.title("My Button Increaser")
global counter
counter = 0
def nClick():
global counter
counter += 1
mButton1.config(text = counter)
mButton1 = Button(text = counter, command = nClick, fg = "darkgreen", bg = "white")
mButton1.pack()
root.mainloop()
hope that helps!
You could use Tkinter variables. They are specially useful when you need to modify a data that other widgets might interact with. Here is a look alike code to the one in the question, but instead of defining counter as a normal variable, it is a variable from Tkinter.
import tkinter
import sys
root = tkinter.Tk()
root.geometry("200x200")
root.title("His Button Increaser")
counter = tkinter.IntVar()
def onClick(event=None):
counter.set(counter.get() + 1)
tkinter.Label(root, textvariable=counter).pack()
tkinter.Button(root, text="Increase", command=onClick, fg="dark green", bg = "white").pack()
root.mainloop()
Instead of passing the value this variable holds to the text attribute of the Label, we assign the variable to textvariable attribute, so when the value of the variable gets updated, Label would update the displayed text accordingly.
When you want to change the value of the variable, you'd need to call the set() method of the variable object (see onClick) instead of assigning the value directly to it.

Tkinter, Trying to generate Checkbutton in loop

I am trying to generate standalone Checkbuttons in loop but who has the same name Checkbutton works together. I don't know where is my mistake...
#!/usr/bin/env python
#-*-coding:utf-8-*-
import os
from Tkinter import *
import ttk
def checkBoxText(st):
if st == 0:
st="Disabled"
if st == 1:
st="Enabled"
return st
root = Tk()
winSt={1:1,2:1,3:0,4:0}
cbTexts={}
cbVariables={}
cb={}
cb_x={ "1":"0.0", "2":"0.0", "3":"0.6", "4":"0.6" }
cb_y={"1": "0.1", "2": "0.8", "3": "0.1", "4": "0.8"}
for i in sorted(winSt.keys()):
cbTexts[i] = StringVar()
cbTexts[i].set(checkBoxText(winSt[i]))
cbVariables[i] = IntVar()
cbVariables[i].set(winSt[i])
cb[i] = Checkbutton(root, text=cbTexts[i].get(), variable=cbVariables[i].get())
cb[i].place(relx=cb_x[str(i)], rely=cb_y[str(i)], relheight=0.1,relwidth=0.4)
mainloop()
The problem is in this line:
cb[i] = Checkbutton(..., variable=cbVariables[i].get())
When you use the variable attribute, you must give it a reference to a variable object, not the value contained in the object. Change the code to this:
cb[i] = Checkbutton(..., variable=cbVariables[i])
You're making a somewhat similar mistake with the checkbutton text. You are creating a StringVar, but then using the value of the StringVar for the checkbutton text instead of the actual variable. Syntactically that's correct when used with the text attribute, but it's doing more work than it needs to. You should either use the textvariable attribute, or simply not create a StringVar.
Here's how to use the textvariable attribute instead of the text attribute:
cb[i] = Checkbutton(root, textvariable=cbTexts[i], ...)
You don't need the StringVar at all if this text will never change. If that's the case, you can just do this and save a couple lines of code:
cb[i] = Checkbutton(root, text=checkBoxText(winSt[i]), ...)

Setting default value of a checkbutton in a menu to True

Goal
I am creating a menu inside an application. In that I want a radiobutton. And by default I want the radiobutton, to be in the on state.
Research
I found how to add the radiobutton using the options.add_radiobutton() command here
TKinter effbot . But I still don't know which of the options needs to be used so that in the default it is set to on.
Code
optionsmenu = Menu(menubar,tearoff=0)
optionsmenu.add_radiobutton(label='Pop Up set to on??',command=self.togglePopUp)
code for self.togglePopUp:
def togglePopUp(self,event=None):
if self.showPopUp:
self.showPopUp = False
else:
self.showPopUp = True
I will initialise self.showPopUp as True.
Please Help me with setting the radiobutton to the on position in the default mode.
If you want to toggle boolean values, I suggest you to use add_checkbutton() instead of add_radiobutton().
With the radiobutton you only have a static value option, which does not change when the entry is clicked. On the other hand, checkbuttons allow you to change between the onvalue and offvalue options.
self.var = IntVar(root)
self.var.set(1)
optionsmenu.add_checkbutton(label='Pop Up set to on??', command=self.togglePopUp,
variable=self.var, onvalue=1, offvalue=0)
Note that the IntVar you have to use as variable for the meny entry can replace the self.togglePopUp variable.
As mentioned by #A Rodas:
self.var = IntVar()
self.var.set(1)
optionsmenu.add_checkbutton(label='Pop Up set to on??', command=self.togglePopUp,
variable=self.var, onvalue=1, offvalue=0)
And to get back the value of this variable use:
if self.var.get() == 1:
self.showpopup()
else:
print 'popup has been disabled. you can toggle this option in the options menu'
Easiest way according to me is to initialize the variable with a default value of 1.
var = IntVar(value=1)

Categories

Resources