How to avoid AttributeError: '_tkinter.tkapp' object has no attribute 'PassCheck' - python

I have read previous posts regarding this error but could not identify what i was doing wrong.Please can someone help me understand what i am doing wrong,thank you.
from tkinter import *
class Passwordchecker():
def __init__(self):
self= Tk()
self.geometry("200x200")
self.title("Password checker")
self.entry=Entry(self)
self.entry.pack()
self.button=Button(self,text="Enter",command= lambda: self.PassCheck(self.entry,self.label))
self.button.pack()
self.label=Label(self,text="Please a password")
self.label.pack()
self.mainloop()
def PassCheck(self1,self2):
password = self1.get()
if len(password)>=9 and len(password)<=12:
self2.config(text="Password is correct")
else:
self2.config(text="Password is incorrect")
run = Passwordchecker()

What triggered the error?
You get this error message:
AttributeError: '_tkinter.tkapp' object has no attribute 'PassCheck'
Because when an instance of Passwordchecker() is initialized, it stumbles on the mainloop() method of your __init__() which does not let your program to recognize any further method belonging to that instance. As a rule of thumb, NEVER run mainloop() inside __init__(). This fixes fully the error message you got above. However, we have other things to fix, and for that, let us redesign your program:
Design
It is better to resort to an other method you call inside __init__() to draw your GUI. Let us call it initialize_user_interface().
When it comes to PassCheck(), you need first to past the object itself to this method. This means the first argument to pass to this method is self. And that is the only argument we need in fact PassCheck(self) because you can access from this method the remaining argument you passed uselessly to it.
Program
So here is the full program you need:
import tkinter as tk
class Passwordchecker(tk.Frame):
def __init__(self, parent):
tk.Frame.__init__(self, parent)
self.parent = parent
self.initialize_user_interface()
def initialize_user_interface(self):
self.parent.geometry("200x200")
self.parent.title("Password checker")
self.entry=tk.Entry(self.parent)
self.entry.pack()
self.button=tk.Button(self.parent,text="Enter", command=self.PassCheck)
self.button.pack()
self.label=tk.Label(self.parent,text="Please a password")
self.label.pack()
def PassCheck(self):
password = self.entry.get()
if len(password)>=9 and len(password)<=12:
self.label.config(text="Password is correct")
else:
self.label.config(text="Password is incorrect")
if __name__ == '__main__':
root = tk.Tk()
run = Passwordchecker(root)
root.mainloop()
Demo
Here is a screenshot of the running program:

Related

Tkinter escape binding not destroying

I am trying to learn tkinter and the idea that I have requires it to be in fullscreen. Before making it fullscreen, however I wanted to make sure I could close the window using escape. So through other questions similar to this one on Stack Overflow I have been trying to get it to destroy the tkinter window when I hit escape. To me this seems like it should work but I am getting an exception when I hit escape:
`Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Jake\AppData\Local\Programs\Python\Python36-
32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
TypeError: destroy() takes 1 positional argument but 2 were given`
This is confusing for me because I don't think I am calling any arguments at all let alone 2. I have added a quit button which calls the close method I made and that works but using escape doesn't seem to. I have supplied my code for clarity. I know this is similar to a lot of questions on here but I have tried everything and nothing seems to be working for me. Thanks in advance!
import tkinter
from tkinter import *
class Window(Frame):
def __init__(self, master = None):
Frame.__init__(self, master)
master.bind('<Escape>', master.destroy)
self.init_window()
def init_window(self):
self.pack(fill=BOTH, expand=1)
quitButton = Button(self, text="quit", command=self.close)
quitButton.place(x=0, y=0)
def close(self):
self.master.destroy()
def main():
root = Tk()
root.geometry('500x500')
app = Window(root)
root.mainloop()
main()
When you bind a function to an event, tkinter will always pass an event object to that function. The destroy function takes no arguments, which means you can't bind directly to it. You need to bind to a function that will accept the event object as an argument.
Since you already have a function, you can give it an optional named argument so that you can continue to call your function without the argument, but it can also be used in a binding:
class Window(Frame):
def __init__(self, master = None):
...
master.bind('<Escape>', self.close)
def close(self, event=None):
self.master.destroy()
You could also use an anonymous function:
master.bind('<Escape>', lambda event: master.destroy())
The following code works.
I used it in a class for creating a full screen app in a 800x480 touch screen for pi:
class FullScreenApp(object):
def __init__(self, master, **kwargs):
self.master=master
pad=3
self._geom='200x200+0+0'
master.geometry('{}x{}'.format(800,480))
master.bind('<Escape>', self.close)
def close(self, event=None):
self.master.destroy()

Python attribute error in a class

I want to create some frames in Tkinter, that should be updated periodically.
Here is the code for on of them:
from Tkinter import *
import time
import random
class KopfFrame:
def __init__(self,master):
frame = Frame(master,bg="tan")
frame.pack(side=TOP,expand=YES, fill=BOTH)
self.ZeitLabel = Label(frame)
self.ZeitLabel.pack(side=RIGHT, expand=NO,ipadx=2, ipady=2)
self.refresh()
def refresh(self):
self.ZeitLabel.configure(text=time.strftime("%H:%M:%S"))
# call this function again in 5 seconds
#print(self)
self.after(5000, self.refresh)
root = Tk()
K = KopfFrame(root)
root.mainloop()
But, when I run it, I have the error:
AttributeError: KopfFrame instance has no attribute 'after'
I am pretty sure, that the way of calling is the problem. So if someone could help me, thaf I would either be thankful for a hint to a good tutorial for functions, classes an how to call an use them.
You are trying to call self.after(), with self being an instance of your KopfFrame class. That class does not have such a method defined.
Perhaps you wanted to call the Frame.after() method here. You'll need to store a reference to the Frame object you pass in first, then call after on that:
class KopfFrame:
def __init__(self,master):
# make frame an attribute on self
self.frame = Frame(master, bg="tan")
self.frame.pack(side=TOP,expand=YES, fill=BOTH)
self.ZeitLabel = Label(self.frame)
self.ZeitLabel.pack(side=RIGHT, expand=NO,ipadx=2, ipady=2)
self.refresh()
def refresh(self):
self.ZeitLabel.configure(text=time.strftime("%H:%M:%S"))
# now you can reach the frame and call after on that:
self.frame.after(5000, self.refresh)
What I changed:
Instead of making frame only a local in the KopfFrame.__init__ method, make it an attribute on self.
Use the self.frame reference to the frame in KopfFrame.refresh() to access the Frame.after() method.

Error when creating a Toplevel widget in Python

I'm coding an application to control serial connected device, right now I'm stuck in a GUI error, here is the simplified code:
import Tkinter
class PaginaPrincipale(Tkinter.Tk):
def __init__(self, parent):
Tkinter.Tk.__init__(self, parent)
def connetti():
pagina_connessione=Tkinter.Toplevel()
pagina_connessione.title("Gestione connessione")
pagina_connessione.mainloop()
self.parent = parent
self.grid()
self.gestisci_connessione = Tkinter.Button(self, text="Connetti!", command=connetti)
self.gestisci_connessione.grid(row=0, column=0, sticky='EW')
if __name__ == "__main__":
applicazione = PaginaPrincipale(None)
applicazione.title = 'Pannello di controllo'
applicazione.mainloop()
When I run the program I get this error:TypeError: 'str' object is not callable
I'm new to Python2.7, I hope someone could tell me what I did wrong!
The widget has a method named title, which you can use to set the title. However, you are replacing this function with a string when you do this:
applicazione.title = 'Pannello di controllo'
Once you've done that, any subsequent attempt to call the function title will result in the error you get (ie: you can't "call" a string).
Instead, you need to call title as a function:
applicazione.title('Pannello di controllo')

Getting the value of a checkbox

This is code I found when searching to understand and learn about Tkinter, but it gives an error on check box toggle.
from Tkinter import *
class Example(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Windows")
Label(text="Contact List").grid(row=0,column=0,columnspan=2)
Text(width=30,height=15).grid(row=1,rowspan=9, column=0,columnspan=2,padx=20)
Button(text="Display Contact").grid(row=10, column=0,columnspan=2,pady=10)
Label(text="Last Name:").grid(row=11, column=0,pady=10)
Entry().grid(row=11,column=1)
Button(text="Search").grid(row=12,column=0,columnspan=2)
Label(text="New Contact").grid(row=0,column=2,columnspan=2)
Label(text="First Name:").grid(row=1,column=2,sticky=E)
Entry().grid(row=1,column=3)
Label(text="Last Name:").grid(row=2,column=2,sticky=E)
Entry().grid(row=2,column=3)
Label(text="Phone #:").grid(row=3,column=2,sticky=E)
Entry().grid(row=3,column=3)
friend_check = IntVar()
Checkbutton(variable=friend_check, command = self.friend_box, onvalue=1, offvalue=0, text = "Friend").grid(row=4,column=3,sticky=W)
#Label(text="Friend").grid(row=4,column=3,padx=20,sticky=W)
Label(text="Email:").grid(row=5,column=2,sticky=E)
Entry().grid(row=5,column=3)
Label(text="Birthday:").grid(row=6,column=2,sticky=E)
Entry().grid(row=6,column=3)
Button(text="Add Contact").grid(row=7,column=3,sticky=E)
def friend_box(self):
if self.friend_check.get() == 1:
print '1'
else:
print '0'
def main():
root = Tk()
root.geometry("600x450+900+300")
root.resizable(0,0)
app = Example(root)
root.mainloop()
if __name__ == '__main__':
main()
This is the error mentioned above:
AttributeError: Example instance has no attribute 'friend_check'
Exception in Tkinter callback
How can I avoid this error?
You're taking too many shortcuts in your code. Let's look at an example:
Label(text="Contact List").grid(row=0,column=0,columnspan=2)
This creates a Label, but doesn't save a reference to it. It will display in the GUI, but if you ever want to refer back to it, you'll be unable to. This is important when you have something like an Entry widget, to which you're pretty much guaranteed to want to use again (for the get()).
Another issue is that you have the geometry management chained to the widget creation. If you did save a reference to this, it would simply point to None, which is the value returned by geometry management methods.
To fix this, unchain the statements and save a reference:
self.cl_label = Label(text="Contact List")
self.cl_label.grid(row=0,column=0,columnspan=2)
Do this for each widget you create.
For friend_check, you need to make it an instance variable instead of a local variable, as local variables are not usable outside their scope and get discarded when the containing function ends. Do this by prepending self. to the reference name.
self.friend_check = IntVar()

Passing function into tkinter object

I am creating a virtual keyboard using tkinter in python 3.4.
class Keyboard(Frame):
def __init__(self, root, callback):
Frame.__init__(self, root, callback)
self.pack()
callback is going to be a function invoked when user presses a key.
So I will run it like:
def press(key):
print(key)
root = Tk()
keyb = Keyboard(root, press)
keyb.grid()
root.mainloop()
However, this must not be the right way to pass the function press into Keyboard because I get an error "AttributeError: 'function' object has no attribute 'items'"
So how do I pass this function into Keyboard?
First of all, don't mix pack and grid. See http://effbot.org/tkinterbook/pack.htm
Second, the Frame class does not take a callback parameter, but in your code you called it with one:
Frame.__init__(self, root, callback)
See http://effbot.org/tkinterbook/frame.htm#reference for correct usage.
What you're looking for would be like this, where callback was removed completely from Keyboard:
def press(key):
print(key)
root = Tk()
keyb = Keyboard(root)
keyb.bind("<Key>", key)

Categories