Setting default value of a checkbutton in a menu to True - python

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)

Related

How to change the value of an option menu after user clicks?

I'm playing around with option menu. I have a list of countries called options. The option menu is set to the first index of options. How can I update the value if a user clicks on a different country? Basically the function doesn't work even though I click on the 2nd (options[1]) country in the option menu.
def first_country():
from_country = start_clicked.get()
if from_country == options[1]:
my_pic = Image.open("usa_flag.png")
resized = my_pic.resize((200, 100), Image.ANTIALIAS)
new_pic = ImageTk.PhotoImage(resized)
flag_label = Label(root, image=new_pic)
flag_label = Label(root, text="function works")
flag_label.grid(row=3, column=0)
start_clicked = StringVar()
start_clicked.set(options[0])
dropdown = OptionMenu(root, start_clicked, *options, command=first_country())
command=first_country() should be command=first_country instead. The former one will execute the function immediately and assign None (result of the function) to command option.
Also the callback for command option of OptionMenu expects an argument which is the selected item:
def first_country(from_country):
if from_country == options[1]:
my_pic = Image.open("usa_flag.png")
resized = my_pic.resize((200, 100), Image.ANTIALIAS)
new_pic = ImageTk.PhotoImage(resized)
# better create the label once and update its image here
flag_label.config(image=new_pic)
flag_label.photo = new_pic # save a reference of the image
...
dropdown = OptionMenu(root, start_clicked, *options, command=first_country)
...
# create the label for the flag image
flag_label = Label(root)
flag_label.grid(row=3, column=0)
...
Note that I have created the label for the flag image once and update its image inside the function instead. Also you need to save the reference of the image if it is created inside a function, otherwise it will be garbage collected.
In Python, whenever you add () to the end of a function, it invokes it. (aside from declaration)
This being the case, it is usually so that when you are to pass a function to something, you need only pass a reference to the function
Effectively, just remove the ()
dropdown = OptionMenu(root, start_clicked, *options, command=first_country)
Comment from acw1668 explained it well:
command=first_country() should be command=first_country instead. The former one will execute the function immediately and assign None to command.

Widget validation in tkinter

I want the user to be able to enter an integer value in the Spinbox widget. If the value entered is not an integer or is an integer outside the Spinbox limits, as soon as the Spinbox loses focus, the value in the Spinbox's content must revert to a default value.
In the example code, I use the Entry widget just for the Spinbox can lose focus.
If the user comes back to Spinbox to enter a new value, his entry is not validated.
I confirm Malcolm's remark in Interactively validating Entry widget content in tkinter that the validatecommand=command feature gets cleared as soon as this command updates the widget's value.
Is there a way to get the value entered in the Spinbox repeatedly validated and not just once?
from tkinter import *
class GUI:
def __init__(self):
# root window of the whole program
self.root = Tk()
self.root.title('Validate Spinbox')
# registering validate and invalid commands
validate_cmd = (self.root.register(self.validate), '%P')
invalid_cmd = (self.root.register(self.invalid))
# creating a Label
items_lbl = Label(self.root, text="# of items (5-10):")
items_lbl.grid(row=0, column=0)
# creating a Spinbox widget
self.items_var = StringVar()
self.items_var.set(7)
items_count = Spinbox(self.root, textvariable=self.items_var,
from_=5, to=10, width=4, validate='focusout',
validatecommand=validate_cmd,
invalidcommand=invalid_cmd)
items_count.grid(row=0, column=1)
# creating an Entry widget
self.entry_var = StringVar()
self.entry_var.set("Input some text here")
text_entry = Entry(self.root, textvariable=self.entry_var)
text_entry.grid(row=1, column=0)
def validate(self, entry):
try:
value = int(entry)
valid = value in range(5, 11)
except ValueError:
valid = False
if not valid:
self.root.bell()
return valid
def invalid(self):
self.items_var.set(7)
if __name__ == '__main__':
main_window = GUI()
mainloop()
I found a great explanation here (in the last paragraph of the chapter Validation):
http://stupidpythonideas.blogspot.fr/2013/12/tkinter-validation.html
If your validatecommand (or invalidcommand) modifies the Entry directly or indirectly (e.g., by calling set on its StringVar), the validation will get disabled as soon as your function returns. (This is how Tk prevents an infinite loop of validate triggering another validate.) You have to turn it back on (by calling config). But you can't do that from inside the function, because it gets disabled after your function returns.
But you need to apply some changes to be able to use this trick.
You need to make the Spinbox an instance attribute, with self :
self.items_count = Spinbox(self.root, textvariable=self.items_var,
from_=5, to=10, width=4, validate='focusout',
validatecommand=validate_cmd,
invalidcommand=invalid_cmd)
self.items_count.grid(row=0, column=1)
And then you can call self.items_count.after_idle(...) inside the validate method :
def validate(self, entry):
try:
value = int(entry)
valid = value in range(5, 11)
except ValueError:
valid = False
if not valid:
self.root.bell()
self.items_count.after_idle(lambda: self.items_count.config(validate='focusout'))
return valid

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

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.

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.

Python TextBox entry Hint(Invisible text) [duplicate]

I have the following Entry box where due to obtaining values I have put a list option in for textvariable.
However I was wondering if it would be possible to put a default text in the background so to show which values are required in each box (like a greyscale text, 'Value 1, value 2 etc..).
self.numbers = [StringVar() for i in xrange(self.number_boxes) ] #Name available in global scope.
box=Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i])
Can I add in maybe something change 'textvariable' upon a mouse click inside the box or can I simply just add in another textvariable or text to set a default text?
self.box = []
for i in xrange(self.number_boxes):
self.clicked = False
self.box.append(Entry(self.frame_table,bg='white',borderwidth=0, width=10, justify="center", textvariable=self.numbers[i], fg='grey'))
self.box[i].grid(row=row_list,column=column+i, sticky='nsew', padx=1, pady=1)
self.box[i].insert(0, "Value %g" % float(i+1))
self.box[i].bind("<Button-1>", self.callback)
In order to put default text in your Entry widget, you can use the insert() method as described here.
box.insert(0, "Value 1") # Set default text at cursor position 0.
Now in order to change the contents of box after the user performs a mouse click inside the box, you will need to bind an event to the Entry object. For example, the following code deletes the contents of the box when it is clicked. (You can read about event and bindings here.) Below I show a full example of this.
Note that deleting the text in the box is probably only practical for the first click (i.e. when deleting the default contents), so I created a global flag clicked to keep track of whether it has been clicked.
from tkinter import Tk, Entry, END # Python3. For Python2.x, import Tkinter.
# Use this as a flag to indicate if the box was clicked.
global clicked
clicked = False
# Delete the contents of the Entry widget. Use the flag
# so that this only happens the first time.
def callback(event):
global clicked
if (clicked == False):
box[0].delete(0, END) #
box[0].config(fg = "black") # Change the colour of the text here.
clicked = True
root = Tk()
box = [] # Declare a list for the Entry widgets.
box.append(Entry(fg = "gray")) # Create an Entry box with gray text.
box[0].bind("<Button-1>", callback) # Bind a mouse-click to the callback function.
box[0].insert(0, "Value 1") # Set default text at cursor position 0.
box.append(Entry(fg = "gray")) # Make a 2nd Entry; store a reference to it in box.
box[1].insert(0, "Value 2")
box[0].pack() #
box[1].pack()
if __name__ == "__main__":
root.mainloop()

Categories

Resources