I would like to have a window with a single button (with text "Click"). When I click the button a new window should open. And in that second window I would like to have 2 radiobuttons and a button (with text "Print"). Clicking that button ("Print") should print the current value of the variable my_variable, which indicates which Radiobutton is choosen.
The first code is missing the first window, but it prints out the correct values. The second code, where I added the first window (with the button "Click" opening the second window) prints always the default value of the variable my_variable. What should I change to get the current value every time a press the button "Print"?
I use tkinter with Python 3.7.
Working code:
import tkinter as tk
def function():
"""That function print the current value of my_variable, depending on which radiobutton was choosen."""
value = my_variable.get()
print(value)
window = tk.Tk()
window.title("Title")
window.geometry('200x200')
my_variable = tk.IntVar(value=0)
rbtn1 = tk.Radiobutton(window, text='one', value=1, variable=my_variable)
rbtn1.grid(row=0, column=0)
rbtn2 = tk.Radiobutton(window, text='two', value=2, variable=my_variable)
rbtn2.grid(row=1, column=0)
button = tk.Button(window, text="Print", command=function)
button.grid(row=2, column=0)
window.mainloop()
Not working code:
import tkinter as tk
def on_click():
def function():
"""That function shoud print the current value of my_variable, depending on which radiobutton was choosen. But it prints the default value instead."""
value = my_variable.get()
print(value)
window = tk.Tk()
window.title("Title")
window.geometry('200x200')
my_variable = tk.IntVar(value=0)
rbtn1 = tk.Radiobutton(window, text='one', value=1, variable=my_variable)
rbtn1.grid(row=0, column=0)
rbtn2 = tk.Radiobutton(window, text='two', value=2, variable=my_variable)
rbtn2.grid(row=1, column=0)
button = tk.Button(window, text="Print", command=function)
button.grid(row=2, column=0)
window_main = tk.Tk()
window_main.title("Title main")
window_main.geometry('400x400')
button = tk.Button(window_main, text="Click", command=lambda: on_click())
button.grid(row=0, column=0)
window_main.mainloop()
The problem is you're calling tk.Tk() twice. When you want to create another window, use tk.Toplevel() instead.
To avoid needing to do that, just change the one line indicated below:
import tkinter as tk
def on_click():
def function():
"""That function should print the current value of my_variable, depending on which radiobutton was chosen. But it prints the default value instead."""
value = my_variable.get()
print(value)
window = tk.Toplevel() ##### CHANGED.
window.title("Title")
window.geometry('200x200')
my_variable = tk.IntVar(value=0)
rbtn1 = tk.Radiobutton(window, text='one', value=1, variable=my_variable)
rbtn1.grid(row=0, column=0)
rbtn2 = tk.Radiobutton(window, text='two', value=2, variable=my_variable)
rbtn2.grid(row=1, column=0)
button = tk.Button(window, text="Print", command=function)
button.grid(row=2, column=0)
window_main = tk.Tk()
window_main.title("Title main")
window_main.geometry('400x400')
button = tk.Button(window_main, text="Click", command=lambda: on_click())
button.grid(row=0, column=0)
window_main.mainloop()
If you want to understand why you should avoid calling Tk() more than once, see the answer to Why are multiple instances of Tk discouraged?
See:
When you click a button in the main window, it calls on_click.
Inside on_click, you every time reassign the variable value: my_variable = tk.IntVar(value=0).
This is why the value of my_variable is not preserved between clicks of the button in the main window.
You need to keep my_variable outside on_click, and initialize it once, not on every click.
A nice way to do that is to make on_click accept it as a parameter: def on_click(my_variable), and command=lambda: on_click(my_variable).
A quick and pretty dirty way is to use global; it's acceptable in a throwaway script, but will quickly become ugly and hard to reason about.
Related
from tkinter import *
def Click():
label = Label(root, text="You clicked it")
label.pack()
root = Tk()
label2 = Label(root, text="You can only click one time")
Button = Button(root, text="Click me", padx=20, pady=20, state=NORMAL,
command=Click,state=DISABLED)
Button.pack()
label2.pack()
root.mainloop()
Because I use state 2 times I am getting this error:
SyntaxError: keyword argument repeated: state
How can I fix this error and make a button that can be clicked one time?
This should do what you want. The idea is to update the button's state from within the click handler function.
FYI, star imports can cause trouble and are best avoided, so I've done that here. I've also changed some variable names to use lowercase, since capitalized names are typically reserved for class objects in Python (things like Label and Tk, for instance!)
import tkinter as tk
def click():
label = tk.Label(root, text="You clicked it")
label.pack()
button.config(state=tk.DISABLED) # disable the button here
root = tk.Tk()
label2 = tk.Label(root, text="You can only click one time")
button = tk.Button(root, text="Click me", padx=20, pady=20, command=click)
button.pack()
label2.pack()
root.mainloop()
Bonus Round - if you want to update the existing label (label2, that is) instead of creating a new label, you can also accomplish this with config
def click():
label2.config(text="You clicked it") # update the existing label
button.config(state=tk.DISABLED) # disable the button here
I would like to write a tkinter app that will automatically update a value based on the current state of the OptionMenu object. Here's what I have so far
from tkinter import *
root = Tk()
def show():
myLabel=Label(root,text=clicked.get()).pack()
clicked=StringVar()
clicked.set("1")
drop = OptionMenu(root,clicked,"1","2","3")
drop.pack()
myButton = Button(root,text="show selection",command=show)
root.mainloop()
In this version, the text can only be updated by clicking a button. How can I make the text update automatically, without this "middle man"?
You can simply assign clicked to the textvariable of the Label, then whenever an option is selected, the label will be updated:
import tkinter as tk
root = tk.Tk()
clicked = tk.StringVar(value="1")
drop = tk.OptionMenu(root, clicked, "1", "2", "3")
drop.pack()
tk.Label(root, textvariable=clicked).pack()
root.mainloop()
After changing some things, i got it working.
It is better to use the config() function to change item's attributes, and another important thing is to not pack() the objects (the Label, in this case) in the same line that the variable declaration.
Like so, you'll be able to change the text. Here is your code updated!
from tkinter import *
def show():
myLabel.config(text = clicked.get())
root = Tk()
clicked=StringVar( value="1")
myLabel=Label(root, text="click the button at the bottom to see this label text changed")
myLabel.pack()
drop = OptionMenu(root, clicked, "1","2","3")
drop.pack()
myButton = Button(root, text="show selection", command=show)
myButton.pack()
root.mainloop()
I have a GUI using Tkinter, it has a main screen and then when you press a button a popup window appears, where you select a checkbutton and then a email will get sent to you.
Not matter what I do, I cannot read the value of the checkbutton as 1 or True it always = 0 or False.
This is my code:
import tkinter as tk
from tkinter import *
import time
root = tk.Tk()
root.title('Status')
CheckVar1 = IntVar()
def email():
class PopUp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
popup = tk.Toplevel(self, background='gray20')
popup.wm_title("EMAIL")
self.withdraw()
popup.tkraise(self)
topframe = Frame(popup, background='gray20')
topframe.grid(column=0, row=0)
bottomframe = Frame(popup, background='gray20')
bottomframe.grid(column=0, row=1)
self.c1 = tk.Checkbutton(topframe, text="Current", variable=CheckVar1, onvalue=1, offvalue=0, height=2, width=15, background='gray20', foreground='snow', selectcolor='gray35', activebackground='gray23', activeforeground='snow')
self.c1.pack(side="left", fill="x", anchor=NW)
label = tk.Label(bottomframe, text="Please Enter Email Address", background='gray20', foreground='snow')
label.pack(side="left", anchor=SW, fill="x", pady=10, padx=10)
self.entry = tk.Entry(bottomframe, bd=5, width=35, background='gray35', foreground='snow')
self.entry.pack(side="left", anchor=S, fill="x", pady=10, padx=10)
self.button = tk.Button(bottomframe, text="OK", command=self.on_button, background='gray20', foreground='snow')
self.button.pack(side="left", anchor=SE, padx=10, pady=10, fill="x")
def on_button(self):
address = self.entry.get()
print(address)
state = CheckVar1.get()
print (state)
time.sleep(2)
self.destroy()
app = PopUp()
app.update()
tk.Button(root,
text="EMAIL",
command=email,
background='gray15',
foreground='snow').pack(side=tk.BOTTOM, fill="both", anchor=N)
screen = tk.Canvas(root, width=400, height=475, background='gray15')
screen.pack(side = tk.BOTTOM, fill="both", expand=True)
def latest():
#Other code
root.after(300000, latest)
root.mainloop()
The popup works perfectly, and the email will print when entered but the value of checkbox is always 0.
I have tried:
CheckVar1 = tk.IntVar() - No success
self.CheckVar1 & self.CheckVar1.get() - No success
Removing self.withdraw() - No success
I only have one root.mainloop() in the script, I am using app.update() for the popup window because without this it will not open.
I have checked these existing questions for solution and none have helped:
Self.withdraw - Can't make tkinter checkbutton work normally when running as script
Self.CheckVar1 - TKInter checkbox variable is always 0
Only one instance of mainloop() - Python tkinter checkbutton value always equal to 0
I have also checked very similar questions but I wasn't going to post them all.
Any help is appreciated.
The problem is that you have two root windows. Each root window gets its own internal tcl interpreter, and the widgets and tkinter variables in one are completely invisible to the other. You're creating the IntVar in the first root window, and then trying to associate it with a checkbutton in a second root window. This cannot work. You should always only have a single instance of Tk in a tkinter program.
because of variable scope
try to put CheckVar1 = IntVar() inside the class
use it with self like this
self.CheckVar1 = tk.IntVar() # object of int
self.CheckVar1.set(1) # set value
variable=self.CheckVar1 # passing to the checkbutton as parameter
state = self.CheckVar1.get() # getting value
I want to open a MessageBox with several Checkboxes to choose some options.
The MessageBox works, but I cannot access the status of the checkboxes.
I can toggle the checkbox (access to the class works) but I am not able to get the status.
How can I get back the Checkboxes status in the main window?
How the program should work:
Main window can create ChooseBox
ChooseBox should give options to choose (here one Option for test example)
Mein window shall get status (tested here with the test button)
(working with python27 and windows - but on ubuntu it did not work neither)
#!/usr/bin/python3
# -*- coding: cp1252 -*-
from Tkinter import *
class ChooseBox(Tk):
def __init__(self):
Tk.__init__(self)
self.var = IntVar()
self.chk = Checkbutton(self, text="Option 1", variable=self.var)
self.chk.pack()
# Button to show the status of the checkbutton
button = Button(self, text='Show Stat',
command=lambda: self.Status(self.var))
button.pack()
def Status(self, var):
print var.get()
def message():
global Choose
Choose = ChooseBox()
Choose.mainloop()
def test():
global Choose
Choose.chk.toggle()
print Choose.var.get()
def main_wrapper(argv):
global Choose
root = Tk()
root.geometry("200x150+30+30")
Button_Frame=Frame(root)
Button_Frame.pack(side=BOTTOM, anchor=W, fill=X, expand=NO)
Button(Button_Frame, text='Make ChooseBox', command=message).pack(side=LEFT, anchor=W, padx=5, pady=5)
# Button to test access to the Box - here it toggles the Checkbutton and (should) prints the status
Button(Button_Frame, text='test', command=test).pack(side=LEFT, anchor=W, padx=5, pady=5)
Button(Button_Frame, text='Quit', command=root.quit).pack(side=RIGHT, anchor=E, padx=5)
root.mainloop()
if __name__ == '__main__':
main_wrapper(sys.argv)
You can not have two Tk() windows, the Tk window is unique and can only be called once. Instead replace the Tk in your choosebox with a Toplevel instead. Other than that I think it should work
I'm trying to use an Entry field to get manual input, and then work with that data.
All sources I've found claim I should use the get() function, but I haven't found a simple working mini example yet, and I can't get it to work.
I hope someone can tel me what I'm doing wrong. Here's a mini file:
from tkinter import *
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
content = entry.get()
print(content) # does not work
mainloop()
This gives me an Entry field I can type in, but I can't do anything with the data once it's typed in.
I suspect my code doesn't work because initially, entry is empty. But then how do I access input data once it has been typed in?
It looks like you may be confused as to when commands are run. In your example, you are calling the get method before the GUI has a chance to be displayed on the screen (which happens after you call mainloop.
Try adding a button that calls the get method. This is much easier if you write your application as a class. For example:
import tkinter as tk
class SampleApp(tk.Tk):
def __init__(self):
tk.Tk.__init__(self)
self.entry = tk.Entry(self)
self.button = tk.Button(self, text="Get", command=self.on_button)
self.button.pack()
self.entry.pack()
def on_button(self):
print(self.entry.get())
app = SampleApp()
app.mainloop()
Run the program, type into the entry widget, then click on the button.
You could also use a StringVar variable, even if it's not strictly necessary:
v = StringVar()
e = Entry(master, textvariable=v)
e.pack()
v.set("a default value")
s = v.get()
For more information, see this page on effbot.org.
A simple example without classes:
from tkinter import *
master = Tk()
# Create this method before you create the entry
def return_entry(en):
"""Gets and prints the content of the entry"""
content = entry.get()
print(content)
Label(master, text="Input: ").grid(row=0, sticky=W)
entry = Entry(master)
entry.grid(row=0, column=1)
# Connect the entry with the return button
entry.bind('<Return>', return_entry)
mainloop()
*
master = Tk()
entryb1 = StringVar
Label(master, text="Input: ").grid(row=0, sticky=W)
Entry(master, textvariable=entryb1).grid(row=1, column=1)
b1 = Button(master, text="continue", command=print_content)
b1.grid(row=2, column=1)
def print_content():
global entryb1
content = entryb1.get()
print(content)
master.mainloop()
What you did wrong was not put it inside a Define function then you hadn't used the .get function with the textvariable you had set.
you need to put a textvariable in it, so you can use set() and get() method :
var=StringVar()
x= Entry (root,textvariable=var)
Most of the answers I found only showed how to do it with tkinter as tk. This was a problem for me as my program was 300 lines long with tons of other labels and buttons, and I would have had to change a lot of it.
Here's a way to do it without importing tkinter as tk or using StringVars. I modified the original mini program by:
making it a class
adding a button and an extra method.
This program opens up a tkinter window with an entry box and an "Enter" button. Clicking the Enter button prints whatever is in the entry box.
from tkinter import *
class mini():
def __init__(self):
master = Tk()
Label(master, text="Input: ").grid(row=0, sticky=W)
Button(master, text='Enter', command=self.get_content).grid(row=1)
self.entry = Entry(master)
self.entry.grid(row=0, column=1)
master.mainloop()
def get_content(self):
content = self.entry.get()
print(content)
m = mini()