Tkinter checkbutton menu doesn't show check indicator - python

When I create a Tkinter menu that includes checkbuttons I can't see the indicator when an item has been clicked. I should see something like this :
However I don't see the little check.
I'm on OS X if this is linked.
Using this code for example who works for someone else :
from tkinter import *
master = Tk()
var = StringVar(master)
var.set("Check")
w = OptionMenu(master, variable = var, value="options:")
w.pack()
first = BooleanVar()
second = BooleanVar()
third = BooleanVar()
w['menu'].add_checkbutton(label="First", onvalue=True, offvalue=False, variable=first)
w['menu'].add_checkbutton(label="Second", onvalue=True, offvalue=False, variable=second)
w['menu'].add_checkbutton(label="Third", onvalue=1, offvalue=False, variable=third)
master.bind('<Button-1>', lambda x: print("First:", first.get(), " - Second:", second.get(), " - Third:", third.get()))
mainloop()
UPDATE
If I set up a Menu widget (not an OptionMenu) then I'll be able to see the little checks. So this only doesn't work for OptionMenu widgets and MenuButton widgets

Related

How to correctly remove focus from entry when checkbutton is selected?

I have seen some answers on SO, however, it does not seem to be the right solution for the use case.
In this example I need to remove focus, disable the Entry and remove its contents when checkbutton is clicked:
from tkinter import *
root = Tk()
def manage_entry():
if bool(var.get()) == False:
e.config(state = 'normal')
if bool(var.get()) == True:
e.delete(0, END)
e.config(state = 'disabled')
# this is not great, but removes focus when checkbutton selected
root.focus()
var = BooleanVar()
var_c = Checkbutton(root, text = 'Freeze entry', variable = var, command = manage_entry)
var_c.deselect()
var_c.pack()
e = Entry(root, width = 15)
e.pack()
root.mainloop()
When checkbutton clicked focus is set to the Tk() which produces what I need but seems incorrect usage of the method. It's for sure a workaround but is there a more correct way to disable the focus? I have also tried e.config(takefocus = 0) but this did not remove the focus

Determining what radiobutton was selected tkinter

I am trying to figure out how to use tkinter radio-buttons properly.
I have used this question as a guideline: Radio button values in Python Tkinter
For some reason I can't figure out how to return a variable that is indicative of what the user selected.
Code:
def quit_loop():
global selection
selection = option.get()
root.quit()
return selection
def createWindow():
root = Tk()
root.geometry=('400x400')
option = StringVar()
option.set('none')
R1 = Radiobutton(root, text='Compile', value = 'Compile', var=option)
R2 = Radiobutton(root, text='Create', value = 'Create', var=option)
button = Button(root, text='ok', command=quit_loop)
R1.pack()
R2.pack()
button.pack()
root.mainloop()
when I call createWindow() I would expect the radio-button box to pop up, and after making my selection and pressing 'ok' I expected it to return me a variable selection which relates to the selected button. Any advice? Tkinter stuff is particularly challenging to me because it seems so temperamental.
You need to make option global if you want to access outside of createWindow
Here's an example of your code that will print out the value of the selected radiobutton and then quit when you click the button. I simply had to declare root and options as global:
from tkinter import *
def quit_loop():
global selection
selection = option.get()
root.quit()
return selection
def createWindow():
global option, root
root = Tk()
root.geometry=('400x400')
option = StringVar()
option.set('none')
R1 = Radiobutton(root, text='Compile', value = 'Compile', var=option)
R2 = Radiobutton(root, text='Create', value = 'Create', var=option)
button = Button(root, text='ok', command=quit_loop)
R1.pack()
R2.pack()
button.pack()
root.mainloop()
createWindow()
As far as I know one needs to do two things to communicate with tkinter
widgets: pass a variable, and pass a command. When user interacts with
widgets, tkinter will do two things: update value of variable and call the
function passed in as command. It is up to us to access the value of the
variable inside the command function.
import tkinter as tk
from tkinter import StringVar, Radiobutton
def handle_radio():
print(option.get())
root = tk.Tk()
option = StringVar()
option.set('none')
R1 = Radiobutton(root, text='Compile', value = 'Compile', var=option, command=handle_radio)
R2 = Radiobutton(root, text='Create', value = 'Create', var=option, comman=handle_radio)
R1.pack()
R2.pack()
root.mainloop()
The code prints 'Create' and 'Compile' when user selects the appropriate
radio option.
Hope this helps.
Regards,
Prasanth

How to set checkbuttons to display a word in a label when enough checkbuttons are clicked?

I'm trying to make checkbuttons display a sentence on a label when three of the checkbuttons are clicked.
New to tkinter, here's what I have tried so far.
from tkinter import *
root = Tk()
Check_button_one = IntVar()
Check_button_two = IntVar()
Check_button_three = IntVar()
Checkbutton(root, variable = Check_button_one).pack()
Checkbutton(root, variable = Check_button_two).pack()
Checkbutton(root, variable = Check_button_three).pack()
default_text = ""
updated_text = "what a legend you are!"
while Check_button_one == 1 and Check_button_two == 1 and Check_button_three == 1:
default_text = updated_text
Label_main = Label(root, text = default_text)
Label_main.pack()
Although there is a lot of good advice in #martineau's answer (mainloop(), how to change the label's text), I think the polling approach is not suitable for a GUI application.
Assuming that the CheckButtons are (de)activated by the user (via mouse/keyboard)*, you do not want to regularly check their states. When polling in intervals, you have two problems:
No immediate response to user action: in the worst case, the label's text will only be updated after the interval, i.e. if the interval is 500ms, the label could change 500ms after the checkbutton was clicked.
Most of the time, your code does unnecessarily check the button states although they haven't changed
The correct way to handle user interaction is specifying a callback that is executed whenever the CheckButton's state has changed as a result of a user action. CheckButton takes a command parameter for that purpose:
from tkinter import *
root = Tk()
Check_button_one = IntVar()
Check_button_two = IntVar()
Check_button_three = IntVar()
default_text = ""
updated_text = "what a legend you are!"
Label_main = Label(root, text = default_text)
Label_main.pack()
def checkbuttonCallback():
if Check_button_one.get() and Check_button_two.get() and Check_button_three.get():
Label_main.config(text=updated_text)
else:
Label_main.config(text=default_text)
Checkbutton(root, variable = Check_button_one, command=checkbuttonCallback).pack()
Checkbutton(root, variable = Check_button_two, command=checkbuttonCallback).pack()
Checkbutton(root, variable = Check_button_three, command=checkbuttonCallback).pack()
root.mainloop()
* If you change the CheckButtons' states via code, you can simply check the states after you changed them.
You need to periodically check the status of the Buttons while the GUI mainloop() is running. You can do that in a tkinter app by using the universal widget after method.
For example:
from tkinter import *
root = Tk()
Check_button_one = IntVar()
Check_button_two = IntVar()
Check_button_three = IntVar()
Checkbutton(root, variable = Check_button_one).pack()
Checkbutton(root, variable = Check_button_two).pack()
Checkbutton(root, variable = Check_button_three).pack()
default_text = ""
updated_text = "what a legend you are!"
Label_main = Label(root, text=default_text)
Label_main.pack()
def check_buttons():
if Check_button_one.get() and Check_button_two.get() and Check_button_three.get():
Label_main.config(text=updated_text)
else: # Make sure the default is displayed.
Label_main.config(text=default_text)
root.after(500, check_buttons) # Schedule next check in 500 msecs
check_buttons() # Start polling buttons.
root.mainloop()

How can I make a Tkinter OptionMenu not change the text when an option is selected?

I would like to make a file button on my Tkinter application that displays three of four options to the user. I have this code:
self.file_button_text = StringVar(master)
self.file_button_text.set('File')
self.file_buton = OptionMenu(self, self.file_button_text, "Com Ports", "Bottle Information", "Reset Graphs")
self.file_buton.grid(row=0, column=0)
self.file_button_text.trace("w", self.file_option)
def file_option(self, *args):
print(self.file_button_text.get())
self.file_button_text.set('File')
However, once an option is selected, the text of the button changes to that option. Is there a way I can get the value of the selection without changing the text of the button itself? I tried using trace to see the option selected and then change the text back to File but it takes too long. Is there a better/another way to do this?
An option menu is nothing but a Menubutton with a Menu, and some special code specifically to change the text of the button. If you don't need that feature, just create your own with a Menubutton and Menu.
Example:
import tkinter as tk
root = tk.Tk()
var = tk.StringVar()
label = tk.Label(root, textvariable=var)
menubutton = tk.Menubutton(root, text="Select an option",
borderwidth=1, relief="raised",
indicatoron=True)
menu = tk.Menu(menubutton, tearoff=False)
menubutton.configure(menu=menu)
menu.add_radiobutton(label="One", variable=var, value="One")
menu.add_radiobutton(label="Two", variable=var, value="Two")
menu.add_radiobutton(label="Three", variable=var, value="Three")
label.pack(side="bottom", fill="x")
menubutton.pack(side="top")
root.mainloop()

Changing the content of a label after a checkbox is selected in Tkinter

I have a label that is coded like this that contains text that is set upon running the program.
label_text = StringVar()
label = Label(window,textvariable=label_text)
label_text.set("Off")
I also have a checkbox;
var= IntVar()
Check= Checkbutton(window,text = "On",variable = var,onvalue = 1,offvalue = 0)
These are both packed like this:
label.pack()
Check.pack(side="left")
When the checkbox is checked, I want to have the label change text to "On",
something like this.
if var.get()==1:
label_text.set("On")
The text remains at Off when I check the checkbox. Any help would be appreciated.
There are several ways of updating the label text when the checkbutton state changes.
One possibility is to make the label and the checkbutton share the same StringVar and set the onvalue/offvalue of the checkbutton to "On"/"Off". That way, when the state of the checkbutton changes, the text of the label is automatically updated.
from tkinter import StringVar, Tk, Label, Checkbutton
window = Tk()
label_text = StringVar()
label = Label(window, textvariable=label_text)
label_text.set("Off")
check= Checkbutton(window, text="On", variable=label_text,
onvalue="On", offvalue="Off")
label.pack()
check.pack(side="left")
window.mainloop()
If for some reason you really want the onvalue/offvalue of the checkbutton to be 0/1, you can pass a function to the command option of the checkbutton. This function will change the text of the label depending on the state of the checkbutton.
from tkinter import StringVar, Tk, Label, Checkbutton, IntVar
def update_label():
if var.get() == 1:
label_text.set("On")
else:
label_text.set("Off")
window = Tk()
label_text = StringVar()
label = Label(window, textvariable=label_text)
label_text.set("Off")
var = IntVar()
check= Checkbutton(window, text="On", variable=var,
onvalue=1, offvalue=0, command=update_label)
label.pack()
check.pack(side="left")
window.mainloop()

Categories