I'm trying to learn tkinter gui in python 3.7, I have this code:
from tkinter import *
# Configuración de la ventana principal
root=Tk()
root.title("Cath Config")
#Definición de clases
#Frames
class marco(Frame):
def __init__(self, master=None, color="#F3F3F3", ancho="1024", alto="680", borde="5", tipoborde="groove"):
Frame.__init__(self)
self.master=master
self.config(bg=color,width=ancho,height=alto,bd=borde,relief=tipoborde)
self.pack()
#Configuración del widget frame
mainframe1=marco(master="root")
#Ejecución de la ventana principal
root.mainloop()
The problem is the code "works", when I run that code it shows the root with the main frame without problem, but when i attempt to close the root, it does not closes and throws this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\konoe\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:\Users\konoe\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2061, in destroy
for c in list(self.children.values()): c.destroy()
File "C:\Users\konoe\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 2306, in destroy
if self._name in self.master.children:
AttributeError: 'str' object has no attribute 'children'
The problem is that you've passed a string as the value of the master parameter. That parameter must be a widget, not a string.
mainframe1=marco(master=root)
You should also pass that parameter to the __init__ method:
Frame.__init__(self, master)
Strictly speaking, it's not necessary for this specific code, since the default for the master is the root window. However, if you're going to create a subclass of Frame you should always include the master in the constructor so that the widget can be used in places other than the root window.
One way to handle this is bind the key with the action:
def quit(event):
print "you pressed control c"
root.quit()
root = tk.Tk()
root.bind('<Control-c>', quit)
root.mainloop()
Another way would be to but a Quit button to safely close the Tkinter window.
root=Tk()
root.title("Cath Config")
Button(root, text="Quit", command=quit).pack()
def quit():
global root
root.quit()
Related
New to tkinter, I want a short program to:
create a window to take user input, by means of an entry widget and a submit button
capture the input and return it to main, so that I can do something else with it.
The following code creates the window and captures input, but breaks at the next-to-last line.
from tkinter import *
from tkinter import ttk
class TxtEntryWindow:
def __init__(self):
self.root = Tk()
self.frame = ttk.Frame(self.root).pack()
self.box = ttk.Entry(self.frame)
self.box.pack()
self.but = ttk.Button(self.frame, text='Submit', command=self.capture_txt)
self.but.pack()
self.root.mainloop()
def capture_txt(self):
txt = self.box.get()
return txt
win = TxtEntryWindow()
user_input = win.capture_txt()
print(user_input)
Here's a copy of the error message:
Traceback (most recent call last):
File "C:...\wclass.py", line 22, in
user_input = win.capture_txt()
File "C:...\wclass.py", line 17, in capture_txt
txt = self.box.get()
File "C:...\Python\Python310\lib\tkinter_init_.py", line 3072, in get
return self.tk.call(self._w, 'get')
_tkinter.TclError: invalid command name ".!entry"
I have no idea what this means. I suspect that dependence of "txt" on the button event in the class prevents "win.capture_txt()" in main() at the bottom from fetching the user input.
Can anyone shed light?
Consulted Python's official documentation (unintelligible), Tkinter's official tutorial and command reference. Searched numerous analogies on StackOverflow and on youtube. Googled the error message itself. I've tried to strike out on my own and rewrite the critical command about twenty times. Blind intuition leads nowhere. Stabbing in the dark.
The error means that the entry widget (self.box) has been destroyed when the line user_input = win.capture_txt() is executed.
You can use an instance variable to store the input text instead and access this instance variable after the window is destroyed:
from tkinter import *
from tkinter import ttk
class TxtEntryWindow:
def __init__(self):
self.text = "" # initialize the instance variable
self.root = Tk()
self.frame = ttk.Frame(self.root).pack()
self.box = ttk.Entry(self.frame)
self.box.pack()
self.but = ttk.Button(self.frame, text='Submit', command=self.capture_txt)
self.but.pack()
self.root.mainloop()
def capture_txt(self):
# save the user input into the instance variable
self.text = self.box.get()
self.root.destroy()
win = TxtEntryWindow()
print(win.text) # show the content of the instance variable
I'm new to Graphic User Interface using Python. I was trying to open the Register page after clicking the "Register" button from the Login page. Then, return to the Login page when clicking "Return to Login". But it did not work.
login.py
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
from register import Register
class Login:
def __init__(self):
self.loginw = Tk()
self.loginw.title("Login")
self.loginw.geometry("500x500")
self.signin = Button(self.loginw,width=20, text="Register", command=self.register)
self.signin.place(relx=0.5, rely=0.5, anchor=CENTER)
def register(self):
self.loginw.quit()
win = Toplevel()
Register(win)
w=Login()
w.loginw.mainloop()
register.py
from tkinter import *
from tkinter import messagebox
from tkinter import ttk
class Register:
def __init__(self):
self.reg = Tk()
self.reg.title("Register")
self.reg.geometry("500x500")
self.revert = Button(self.reg,width=20, text="Return to Login")
self.revert.place(relx=0.5, rely=0.5, anchor=CENTER)
The error raised up after clicking the Register button
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\me\AppData\Local\Programs\Python\Python310\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "c:\Users\me\Documents\Education\Testing code\login.py", line 18, in register
Register(win)
TypeError: Register.__init__() takes 1 positional argument but 2 were given
Thank you so much.
When you are calling the Register class's constructor to get a window, you pass the Toplevel instance named win but within the __init__ method of the Register class you are not accepting any arguments to the constructor.
This can be fixed, by accepting another argument in the __init__ method. Further note there is no need to initialize self.reg as tkinter.Tk() then as the Toplevel instance taken as argument will work in it's place.
The Register class definition will change to -:
class Register:
def __init__(self, win):
self.reg = win # new.
self.reg.title("Register")
self.reg.geometry("500x500")
self.revert = Button(self.reg,width=20, text="Return to Login")
self.revert.place(relx=0.5, rely=0.5, anchor=CENTER)
self.reg.mainloop() # new.
Further, Now a new mainloop has to be started for the new window initalized, thus the line self.reg.mainloop() was added.
With the suggested changes in place, the output seems to be as required by the OP -:
I am making an application that involves tkinter, and will eventually involve sockets. My code currently consists of this:
import tkinter as tk # imports tkinter module
from tkinter import * # imports tkinter module
a=tk.Tk()
a.title('Custodian Alert Tool')
List=['','','']
List.clear()
def Clear():
for widget in a.winfo_children(): # clears the window for the next Page
widget.destroy()
def Home():
Clear()
Label(a,text='Welcome to the Custodian Alert Tool.').pack()
Label(a,text='').pack()
SubmitButton=tk.Button(a,text='Submit A Ticket',command=Submit)
SubmitButton.pack()
ExitButton=tk.Button(a,text='Exit',command=Exit)
ExitButton.pack()
a.mainloop()
def Submit():
Clear()
def Append1(): # the button calls this function when pressed
List.append(x.get())
Gender()
Label(a,text='Which bathroom are you reporting for?').pack()
f=tk.Frame(a)
f.pack()
x=tk.StringVar()
E=tk.Entry(f,textvariable=x)
E.grid(row=1,column=1)
b1=tk.Button(f,text='Submit',command=Append1) # the error occurs after I click this button
b1.grid(row=1,column=2)
def Gender():
Clear()
def Append2(y):
List.append(y)
Issue()
Label(a,text='Boys or Girls?').pack()
f=tk.Frame(a)
f.pack()
b1=tk.Button(f,text='Boys',command=Append2('Boys'))
b1.grid(row=1,column=1)
b2=tk.Button(f,text='Girls',command=Append2('Girls'))
b2.grid(row=1,column=2)
def Issue():
Clear()
def Exit():
a.destroy()
Home()
When I click the b1 button under the Submit function, however, I get this:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 1550, in __call__
return self.func(*args)
File "/Users/skor8427/Desktop/AlertClient.py", line 27, in Append1
Gender()
File "/Users/skor8427/Desktop/AlertClient.py", line 45, in Gender
b1=tk.Button(f,text='Boys',command=Append2('Boys'))
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 2209, in __init__
Widget.__init__(self, master, 'button', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/3.5/lib/python3.5/tkinter/__init__.py", line 2139, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: bad window path name ".4610182280"
This is the biggest error I have ever gotten and I have no clue where to begin. Anyone know what I can do?
When you do this:
b1=tk.Button(f,text='Boys',command=Append2('Boys'))
It behaves exactly the same as this:
result = Append2('Boys'))
b1=tk.Button(f,text='Boys',command=result)
When Append2 is called, it calls Issue which calls Clear which destroys all of the children in a. f is in a so f gets destroyed. That means that you're trying to create b1 as a child of a widget that has been destroyed. And that is why you get the error "bad window path name" -- that cryptic string is the name of the widget that has been destroyed.
You need to modify the construction of b1 to be something like this:
b1 = Button(f, text='Boys', command=lambda: Append2('Boys'))`
That will defer the calling of Append2 until the button is clicked.
This question already has answers here:
Tkinter: AttributeError: NoneType object has no attribute <attribute name>
(4 answers)
Closed 3 years ago.
I'm trying to get a value from an Entry box which is my input, and I want whatever is written in it to be available for processing on button press. Here is the code I have:
from tkinter import *
import tkinter as tk
class GUI(Tk):
def __init__(self):
super(GUI, self).__init__()
tk.Label(self, text="Input").grid(row=0)
self.input = tk.Entry(self).grid(row=0, column=1)
tk.Button(self, text="Start", command=self.start_button).grid(row=5, column=1)
def start_button(self):
print(self.input.get())
gui = GUI()
gui.mainloop()
Whenever I try to press the button, it says None type has no attribute "get". Here is the traceback:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "D:/Projects/excel_reader/test.py", line 15, in start_button
print(self.input.get())
AttributeError: 'NoneType' object has no attribute 'get'
I have tried removing the TK as subclass for my GUI class, removing the super() call and tried declaring all the variables globally but that did not work either. I am very new to Python GUI.
The problem turns out to be the way I was defining the grids for it. I don't know why but this works now by changing this-> input = tk.Entry(root).grid(row=0, column=1)
to this:
global input
input = tk.Entry(self)
input.grid(row=0, column=1)
from tkinter import*
root = Tk()
shape = Canvas(root)
class GUI():
def __init__(self):
pass
def create_button(self, info, boom, posit):
self.Button(root)
self.config(text=info)
self.bind("<Button-1>",boom)
self.grid(column=posit[0],row=posit[1])
def create_label(self, info, posit):
self.Label(root)
self.config(text=info)
self.grid(column=posit[0],row=posit[1])
def go_away(self):
print("GO AWAY before")
self.button.grid_forget()
print("GO AWAY")
def make_GUI():
root.title("Hexahexaflexagon")
hexahexa = GUI()
quit_butt = GUI()
quit_butt.create_button("Exit","root.destroy()",[0,1])
quit_butt.go_away()
make_GUI()
root.mainloop()
Okay so I am trying to write a class function to just hide (and if not that then delete) a button created by tkinter, I'm new to classes and the error message I keep getting is that the GUI class does not have that function or that object does not have that attribute, I've tried code such as frm.forget(), .lower(), .grid_forget() but there not working for me.
The traceback is:
Traceback (most recent call last):
File "N:\HW\Hexahexaflexagon generator.py", line 94, in <module>
make_GUI()
File "N:\HW\Hexahexaflexagon generator.py", line 63, in make_GUI
quit_butt.go_away()
File "N:\HW\Hexahexaflexagon generator.py", line 51, in go_away
self.button.grid_forget()
AttributeError: 'function' object has no attribute 'grid_forget'
The problem is this line:
self = Button(root)
You are redefining self from referring to the current object, to now refer to a different object. You have the same problem further down with a label. This is simply not how python works.
You must store the widgets as attributes on self, not as self itself.
self.button = Button(root)
...
self.label = Label(root)
Once you do that, you can hide the button or label with grid_forget since you're using grid to make it visible:
self.button.grid_forget()
You have another problem in that you're passing in a command as a string. This will not work the way you think it does. If you want to be able to pass in a function, it needs to be a reference to an actual function:
quit_butt.button("Exit",root.destroy,[0,1])