I am currently writing an application that uses Tkinter to provide a graphical interface for the user.
The app has been working very well and recently I decided to add some checkboxes, the idea being that when the user checks one of the boxes, another set of text is sent through an API.
I have input boxes that I am able to get to work perfectly, however for some reason whenever I try and retrieve the value of the checkbox, I get the following error:
if check.get():
NameError: name 'check' is not defined
For the life of me I can't figure out why this error is popping up, here is the rest of my code, to make it clearer I have removed the working code for the input boxes.
from tkinter import *
class GUI:
def __init__(self, master):
check = IntVar()
self.e = Checkbutton(root, text="check me", variable=check)
self.e.grid(row=4, column=2)
self.macro_button = Button(master, text="Test Button", command=self.test)
self.macro_button.grid(row=11, column=1)
def test(self):
if check.get():
print('its on')
else:
print('its off')
root = Tk()
root.resizable(width=False, height=False)
my_gui = GUI(root)
root.mainloop()
When I run this code, and press the button labeled 'test button', that is when the error appears in my terminal.
Anyone have any idea why this is happening for my checkboxes, and not for my inputboxes?
EDIT:
what's even odder for me is that this code that I found online made to teach you how to use a tkinter checkbox works like a charm, and its almost identical to mine:
import tkinter as tk
root = tk.Tk()
var = tk.IntVar()
cb = tk.Checkbutton(root, text="the lights are on", variable=var)
cb.pack()
def showstate():
if var.get():
print ("the lights are on")
else:
print ("the lights are off")
button = tk.Button(root, text="show state", command=showstate)
button.pack()
root.mainloop()
You just need to make check an instance variable with self.
I.E
class GUI:
def __init__(self, master):
self.check = IntVar()
self.e = Checkbutton(root, text="check me", variable=self.check)
self.e.grid(row=4, column=2)
self.macro_button = Button(master, text="Test Button", command=self.test)
self.macro_button.grid(row=11, column=1)
def test(self):
if self.check.get():
print('its on')
else:
print('its off')
root = Tk()
root.resizable(width=False, height=False)
my_gui = GUI(root)
root.mainloop()
The example you found online is written in an 'inline' style - which is fine until your GUI becomes larger and you require many methods and variables to be used / passed.
Related
Hi I am pretty new to tkinter and have being trying to create a button that opens a window then a have a button in the new window the gives a message when pressed. I ran into the problem that the only whay I could get it to recognise the function I wrote was to write it inside the function that opens the second window. I don't know if I have being searching for the wrong things but I can't find how to do this properly. Can someone help me out Here is my code
from tkinter import *
master = Tk()
master.title("frame control")
def win():
window2 = Toplevel()
def open():
stamp = Label(window2, text="Staped").pack()
lab2 = Button(window2,text = "yo ",command = open).pack()
lab1 = Button(master,text = " open a new window" , command = win).pack()
mainloop()
This is your code but with best practises:
import tkinter as tk
def create_stamp():
stamp = tk.Label(window2, text="Stamp")
stamp.pack()
def create_second_win():
global window2
window2 = tk.Toplevel(root)
lab2 = tk.Button(window2, text="Click me", command=create_stamp)
lab2.pack()
root = tk.Tk()
root.title("Frame control")
button = tk.Button(root, text="Open a new window", command=create_second_win)
button.pack()
root.mainloop()
I made window2 a global variable so that I can access it from create_stamp. Generally it is discouraged to use from ... import *. As #Matiiss said, sometimes you can have problems with global variables if you don't keep track of the variable names that you used.
If you want to avoid using global variables and want to use classes, look at this:
import tkinter as tk
class App:
def __init__(self):
self.stamps = []
self.root = tk.Tk()
self.root.title("Frame control")
self.button = tk.Button(self.root, text="Open a new window", command=self.create_second_win)
self.button.pack()
def create_stamp(self):
stamp = tk.Label(self.window2, text="Stamp")
stamp.pack()
self.stamps.append(stamp)
def create_second_win(self):
self.window2 = tk.Toplevel(self.root)
self.lab2 = tk.Button(self.window2, text="Click me", command=self.create_stamp)
self.lab2.pack()
def mainloop(self):
self.root.mainloop()
if __name__ == "__main__":
app = App()
app.mainloop()
As #Matiiss mentioned it would be more organised if you move the second window to its own class. For bigger projects it is a must but in this case you don't have to.
I've been attempting to make a simple GUI, and have been working my way through tkinter's various functions. However, I can't for the life of me figure out why this doesn't work.
from tkinter import Tk, Label, Button, Radiobutton,IntVar,StringVar
class TestGUI:
def __init__(self, master):
self.master = master
master.title("Test GUI")
self.mode = IntVar()
self.modetext = StringVar()
self.modetext.set("What does this do?")
self.modelabel = Label(master,textvariable=self.modetext)
self.modelabel.pack()
self.close_button = Button(master, text="Close", command=master.destroy)
self.close_button.pack()
R1 = Radiobutton(master, text="Mode 1", variable=self.mode, value=0, command=self.modeset)
R1.pack()
R2 = Radiobutton(master, text="Mode 2", variable=self.mode, value=1, command=self.modeset)
R2.pack()
R3 = Radiobutton(master, text="Mode 3", variable=self.mode, value=2, command=self.modeset)
R3.pack()
def modeset(self):
self.modetext.set("Mode is " + str(self.mode.get()))
print(self.mode.get())
root = Tk()
T_GUI = TestGUI(root)
root.mainloop()
What it should do, as far as I can tell, is display three radio buttons which set the value of mode, and display "Mode is [mode]" in the label and print the value of mode when one is selected.
Instead, the label is never displayed and choosing a radio button doesn't change the value of mode.
Can anyone give me a clue on what is happening?
Looking at your explanation, StringVar and IntVar are causing problems here.
Specifying master on them should solve your issue.
self.mode = IntVar(master=self.master)
self.modetext = StringVar(master=self.master)
Something to do with Pyzo probably because on most IDEs, omitting master don't cause any problems.
I use Tkinter for make a GUI. I have a window with 2 radiobutton ('Yes' and 'No'), but when I select one, it don't run the script :
root = Tk()
Button(root, text='TEST', command=root.quit).pack()
root.mainloop()
master = Tk()
v = IntVar()
Radiobutton(master, text='Yes', variable=v, value=0).pack()
Radiobutton(master, text='No', variable=v, value=1).pack()
Button(master, text='Exit', command=master.quit).pack()
master.mainloop()
print(v.get())
if v.get() == 0:
testy = Tk()
Label(testy, text='Bad').pack()
testy.mainloop()
else:
testn = Tk()
Label(testn, text='Bad').pack()
testn.mainloop()
If I don't have the first window, it works but with it, it don't.
Somebody know how to fix this problem ?
You have initiated several Tk() systems, but there should be only one.
If you want to get a new window then use Toplevel()
No code is executed after mainloop() except for events. The code continues to "flow" after mainloop only after closing the windows.
So here is your code with fixes:
from tkinter import *
root = Tk()
Button(root, text='TEST', command=root.quit).pack()
master = Toplevel()
v = IntVar()
def check_radio():
print(v.get())
if v.get() == 0:
Label(Toplevel(), text='Bad').pack()
else:
Label(Toplevel(), text='Good').pack()
Radiobutton(master, text='Yes', variable=v, value=0, command=check_radio).pack()
Radiobutton(master, text='No', variable=v, value=1, command=check_radio).pack()
Button(master, text='Exit', command=master.quit).pack()
root.mainloop()
Check carefully, I changed the parents of widgets and other changes.
Possible duplicate of tkinter radiobutton not updating variable, but seeing as this question was asked first the answer may make more sense here.
Make sure you are assigning a master to the IntVar like self.rbv=tk.IntVar(master) #or 'root' or whatever you are using):
import Tkinter as tk
import ttk
class My_GUI:
def __init__(self,master):
self.master=master
master.title("TestRadio")
self.rbv=tk.IntVar(master)#<--- HERE! notice I specify 'master'
self.rb1=tk.Radiobutton(master,text="Radio1",variable=self.rbv,value=0,indicatoron=False,command=self.onRadioChange)
self.rb1.pack(side='left')
self.rb2=tk.Radiobutton(master,text="Radio2",variable=self.rbv,value=1,indicatoron=False,command=self.onRadioChange)
self.rb2.pack(side='left')
self.rb3=tk.Radiobutton(master,text="Radio3",variable=self.rbv,value=2,indicatoron=False,command=self.onRadioChange)
self.rb3.pack(side='left')
def onRadioChange(self,event=None):
print self.rbv.get()
root=tk.Tk()
gui=My_GUI(root)
root.mainloop()
try running that, click the different buttons (they are radiobuttons but with indicatoron=False) and you will see it prints correctly changed values!
This is my first python personal project. I am wanting to use Tkinter to create a window (GUARDIAN LOCATOR) that asks the user to input a value (enter sailor guardian) into the entry box. The rest of the program is dependent on what the user types in the entry box as I will be having if/else statements reacting to the sailor guardian entered.
The issue I am having is storing what is entered in the entry box as a variable to use in my main file for the if/else statements. I can get the value to print to the prompt window, but I haven't been able to store it successfully to a global variable.
My Tkinter window is in it's own class.
I have tried many different ways of doing this based on similar issues from stackoverflow, but I am getting an error every time. This is my base code that still produces the error.
Class file with the Tkinter window
class GuardianLocator:
def __init__(self, master):
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
print(self.entry.get())
and in my main working file
root = Tk()
locator = guardian_locator.GuardianLocator(root)
root.mainloop()
This is my test loop to see if it's working.
if locator.guardian_input() is "Sailor Moon":
print("hi")
else:
print("no")
Not sure exactly how your code is organized and where is your "test loop" located, but I assume it is after root.mainloop(). Thus the script can be as follows:
from tkinter import *
class GuardianLocator:
def __init__(self, master):
self._name = ""
frame = Frame(master)
frame.grid()
master.title("GUARDIAN LOCATOR")
self.locator_label = Label(frame, text="Which Sailor Guardian are you looking for?", width=40, height=2)
self.locator_label.grid()
self.entry = Entry(frame)
self.entry.grid()
self.button1 = Button(frame, text="Search", command=self.guardian_name, pady=2)
self.button1.grid()
def guardian_name(self):
self._name = self.entry.get()
print(self.entry.get())
root = Tk()
locator = GuardianLocator(root)
root.mainloop()
# this will be executed after the root window is closed.
print("Name is", locator._name)
Please note self._name = "" in the constructor. This instance variable can be used to store the name provided in your GuardianLocator window.
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()