I'm a having a problem that I can't check if the checkbutton in tkinter is checked or not (I always get False).
I'm sure I'm missing something but I've tried for so long and I don't know what I'm doing wrong.
Bellow is the minimum code I could write that shows the problem:
There are two files:
The main file (that you run) is called "main_GUI.py" and here's the code:
from tkinter import *
import sub_GUI
root = Tk()
button1 = Button(root, bg='white', text="Click me", font=("Helvetica",12),
height=3, width=25, command=sub_GUI.create_new_window)
button1.grid(column=1, row=1)
root.mainloop()
The second file is called "sub_GUI.py" and here's the code:
from tkinter import *
var1 = None
sub_root = None
def create_widgets():
global sub_root
global var1
var1 = BooleanVar()
Checkbutton(sub_root,
text="A",
variable=var1,
command=do_something
).grid(row=2, column=0, sticky=W)
def do_something():
global var1
is_current_joint_checked = var1.get()
if is_current_joint_checked:
print('True')
else:
print('False')
def create_new_window():
global sub_root
sub_root = Tk()
sub_root.title("Movie Chooser")
create_widgets()
The problem is that in the window that appears with the letter 'A' (after you clicked the button), every time I check/uncheck 'A' it prints False (never prints True).
Can anyone tell me what's the problem?
Thanks
Related
I want to set the answer using the set() method without writing it in the text attribute in the Label and also I want to change the message without displaying the messages over each other.
I want the new message to appear and the one before it to disappear. I tried to use the set() and get() methods but it used to return its default value without using the value in the set() method and I don't know why.
from tkinter import *
from tkinter import messagebox
from PIL import ImageTk,Image
root= Tk()
root.title("Project")
root.geometry('500x600')
root.title('Choose Answer')
var = IntVar()
textt = StringVar()
print(textt.set('Clicked..........'))
def Result():
print(textt.set('You Clicked....................'))
if(var.get() == 1):
print(var.get())
print(textt)
textt.set('You Clicked')
resultText = Label(root, text=textt , fg='white',bg='gray', width=40)
resultText.place(x=100,y=200)
else:
textt.set('You did\'t Click')
resultText = Label(root, text=textt, fg='white',bg='grey', width=40)
resultText.place(x=100,y=200)
checkBox = Checkbutton(root, text='Did you Study Math', variable=var, bg='grey')
checkBox.place(x=50,y=50)
button = Button(root, text='Select', fg='white', bg='grey',font='sans-serif',command=Result)
button.place(x=50,y=100)
root.mainloop()
This should work:
from tkinter import *
root = Tk()
root.title("Project")
root.geometry('500x600')
root.title('Choose Answer')
var = IntVar()
textt = StringVar()
resultText = Label(root, textvariable=textt , fg='white',bg='gray', width=40)
resultText.place(x=100,y=200)
def Result():
print(var.get())
if var.get() == 1:
textt.set('You Clicked')
else:
textt.set('You didn\'t Click')
checkBox = Checkbutton(root, text='Did you Study Math', variable=var, bg='grey')
checkBox.place(x=50,y=50)
button = Button(root, text='Select', fg='white', bg='grey',font='sans-serif',command=Result)
button.place(x=50,y=100)
root.mainloop()
When you create resultText, instead of setting the text argument to textt, you need to set the textvariable argument to text. That way, the text of the variable is automatically changed when you change textt.
I removed all the lines where resultText was recreated and re-placed, and just created it once before defining Result(). Also, I removed from tkinter import messagebox, because you already import it when you call from tkinter import *. Just a note: wildcard imports are discouraged, so try to avoid using them in the future.
Here is an example of what I am trying to convey:
from tkinter import *
def start():
print("Start")
B1.pack_forget()
B2.pack()
def stop():
B2.pack_forget()
B1.pack()
root = Tk()
root.title("TestWin")
B1 = Button(root, text='start', command=start)
B1.pack()
B2 = Button(root, text='stop', command=stop)
root.mainloop()
Now I want to use if logic to get the name of the button currently packed. And it could look something like:
if <button_text_keyword> == 'start' then print('Start') elif <button_text_keyword> == 'stop' then print("Stop").
Can this be done??? Or Do I have to type a long code in order to achieve that???
Please suggest a good method to do what I want or rectify me.
Just to be clear, if the goal is just to print whatever text the button is showing, the simplest is to just have separate command functions, as you have done. It's then explicitly clear which button was there at the time of the click. So by this I mean, just add a print statement in the stop function.
But assuming there is a more nuanced situation where you actually need to determine what is packed in a different part of the program, this is an example based on what #acw1668 suggested in the comments:
from tkinter import *
packed = 'B1'
def start():
global packed
B1.pack_forget()
B2.pack()
packed = 'B2'
def stop():
global packed
B2.pack_forget()
B1.pack()
packed = 'B1'
def check():
if packed == 'B1':
print("Start")
elif packed == 'B2':
print("Stop")
root = Tk()
root.title("TestWin")
B1 = Button(root, text='start', command=start)
B1.pack(side=TOP)
B2 = Button(root, text='stop', command=stop)
B3 = Button(root, text='check', command=check)
B3.pack(side=BOTTOM)
root.mainloop()
The new button ("check") determines what button is packed, based on the flag packed (just to note, if you instead wrap the application in class (see here), you could avoid having to use global).
The above is more than sufficient, but if you actually want to check the button object itself, you can check the packed elements in a Frame with pack_slaves():
from tkinter import *
def start():
B1.pack_forget()
B2.pack()
def stop():
B2.pack_forget()
B1.pack()
def check():
global button_frame
button = button_frame.pack_slaves()[0]
text = (button.cget('text'))
if text == 'start':
print('Start')
elif text == 'stop':
print('Stop')
root = Tk()
root.title("TestWin")
button_frame = Frame(root,)
button_frame.pack(side=TOP)
B1 = Button(button_frame, text='start', command=start)
B1.pack()
B2 = Button(button_frame, text='stop', command=stop)
B3 = Button(root, text='check', command=check)
B3.pack(side=BOTTOM)
root.mainloop()
This second example sounds more similar to the logic you described; i.e. find object corresponding to the pressed button, then get its text using cget, and route that to determine what is printed. Note that this example finds the button widget by using button = button_frame.pack_slaves()[0], so there is an assumption that there will only be clearly one button packed in button_frame.
Another option would be to use bind to program the button's effects, rather than the command parameter. You could then create a function like check in the above example to bind to both buttons, and you could use this technique to get the pressed widget (and then check it's identity/text, determine what to print, etc....).
If you want that on clicking the button your button text will get change then you try #this
from tkinter import *
root = Tk()
root.title("title")
def start():
#for changing text on button
button_name.config(text="new text on button")
B1 = Button(root, text='start', command=start)
B1.pack()
I have a check button in my program. when I click the check button, the var value is always 0. Shouldn't the value be 1 when clicked. It works in a small program that i made but when I try to get a check button value in my big program, the value is always 0 no matter how many times I click the checkbutton. The following code is the small example program that I wrote which works just fine but when I try to get the var value in my bigger program, the value is always 0.
from tkinter import *
root = Tk()
root.geometry("400x400")
def check():
global var2
var2 = IntVar()
c=Checkbutton(root, text="click me", variable=var2, command=show)
c.pack()
myButton=Button(root, text="show selection", command=show).pack()
def show():
myLabel = Label(root, text=var2.get()).pack()
check()
root.mainloop()
Well, I figured it out. Well, thanks to Google. When opening up a new window instead of calling Tk() I changed it to Toplevel() and it finally worked. Thanks for all of your input.
You needed to use BooleanVar(). Hope it helps.
from tkinter import *
root = Tk()
root.geometry("400x400")
def check():
global var2
var2 = BooleanVar()
c=Checkbutton(root, text="click me", variable=var2, command=show)
c.pack()
myButton=Button(root, text="show selection", command=show).pack()
def show():
myLabel = Label(root, text=int(var2.get())).pack()
# commented out the lower label, it returned False instead of one.
# It's always a good idea to force variables to be what they should be.
# myLabel = Label(root, text=var2.get()).pack()
check()
root.mainloop()
I'm new to trying out python GUI's and tried tkinter and pyglet, but only through tutorials, in-order-to understand the basic classes and functions. But what I'm currently trying to do is to get a button to increase a number whilst displaying that number at the same time. Somehow, even though the variable number was stated globally as 0, the function to increase it doesn't do anything, it actually produces an error: 'UnboundLocalError: local variable 'number' referenced before assignment'. I have no idea how to correct this.
The tutorials I've seen on both YouTube and as an article, don't talk about how to do this exactly. The article does mention how to change a certain text though, but not a previously created variable (which in my case would be 'number').
from tkinter import *
number = 0
window = Tk()
window.title("Programme")
window.geometry('350x250')
label = Label(window, text=number)
label.grid(column=0,row=0)
def clicked():
number += 1
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
Is there any way to do this?
Also I've been looking for how to add time, to handle events and such, through ticks. But everything I find on the internet is about literally displaying a clock on the GUI, which is useless, or at least I don't know how to use it to have a ticking function.
You need to increment the number, like you do, but also update the Label to display the new number:
from tkinter import *
number = 0
window = Tk()
window.title("Programme")
window.geometry('350x250')
label = Label(window, text=number)
label.grid(column=0,row=0)
def clicked():
global number
number += 1
label.config(text=number)
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
An easier way to do this is to use tkinter's version of an integer: IntVar. It takes care of the Label updates automatically, but it requires you use get() and set() to work with it.
from tkinter import *
def clicked():
number.set(number.get()+1)
window = Tk()
window.title("Programme")
window.geometry('350x250')
number = IntVar()
label = Label(window, textvariable=number)
label.grid(column=0,row=0)
button = Button(window, text="Push Me", command=clicked)
button.grid(column=1, row=2)
window.mainloop()
Here is my entire code:
from tkinter import *
def up():
number.set(number.get()+1)
def down():
number.set(number.get()-1)
window = Tk()
window.title("Programme")
window.geometry('350x250')
number = IntVar()
frame = Frame(window)
frame.pack()
entry = Entry(frame, textvariable=number, justify='center')
entry.pack(side=LEFT, ipadx=15)
buttonframe = Frame(entry)
buttonframe.pack(side=RIGHT)
buttonup = Button(buttonframe, text="▲", font="none 5", command=up)
buttonup.pack(side=TOP)
buttondown = Button(buttonframe, text="▼", font="none 5", command=down)
buttondown.pack(side=BOTTOM)
window.mainloop()
It looks better for me when the buttons are inside of the entry widget directly.
Essentially, I'm using Tkinter in python so that 1 is added to a variable when a button is pushed. I have another variable that is equal to my first variable times 10. When I hit the button that adds one to my original variable, the second variable (x*10) is not doubled. Take a look:
def add1():
var1.set(var1.get() + 1)
def pringvar3()
print(var3.get())
from tkinter import *
main = Tk()
button = Button(main, text="Add 1", command=add1)
button.pack()
button2 = Button(main, text="Print var3", command=printvar3)
button2.pack()
var1 = IntVar()
var1.set(1)
var2 = IntVar()
var2.set(10)
var3 = IntVar()
var3.set(var2.get() * var1.get())
What's wrong with that code? When I click the buttons, first 1 then 2, it still prints the variable as 10.
You have a bunch of spelling errors and missing colons, but more importantly you don't change the value in the function callback. Remember, you only set the value once, you never actually reset it.
def printvar3():
global var3
var3.set(var2.get() * var1.get())
print(var3.get())
tkinter IntVar objects don't update others that may have used their value at some point, so changing var1 won't automatically update var3 -- you have to make it happen explicitly.
Here's a simple demonstration based on your code that has an extra button added that does this when clicked:
def add1():
var1.set(var1.get() + 1)
def updatevar3():
var3.set(var2.get() * var1.get()) # recalulate value
def printvar3():
print(var3.get())
from tkinter import *
main = Tk()
button = Button(main, text="Add 1", command=add1)
button.pack()
button2 = Button(main, text="Update var3", command=updatevar3)
button2.pack()
button3 = Button(main, text="Print var3", command=printvar3)
button3.pack()
var1 = IntVar()
var1.set(1)
var2 = IntVar()
var2.set(10)
var3 = IntVar()
var3.set(var2.get() * var1.get()) # set initial value
main.mainloop()
print('done')