Error when creating a Toplevel widget in Python - 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')

Related

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

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:

Tkinter Button unable to find callback command

I'm working on a program that reads and parses a config file for an embedded hardware system I'm working on. I'm trying to use tkinter and python to make a simple GUI for reading and writing this file. I have the file IO and parsing mostly working, but I'm having trouble getting all the parts integrated with the GUI. I want to read the information off of the device and then populate the entry fields with the relevant info. The problem that I'm having is I keep getting the error
"in initUI
opnBut = Button(butFrm, text="Open", command=openCfg)
NameError: name 'openCfg' is not defined"
I can get it to find the function if I put it outside the Application class but then I can't figure out how to reference the fields inside the window I've made to update them.
Any help would be greatly appreciated. My code segment is included below.
class Application(Frame):
def openCfg():
name = getNameFromFile()
nameEntry.insert(0, name)
def __init__(self, parent):
Frame.__init__(self, parent)
self.parent = parent
self.initUI()
def initUI(self):
self.parent.title("Config Reader")
self.pack(fill=BOTH, expand=True)
nameFrm = Frame(self)
nameFrm.pack(fill=X)
nameLbl = Label(nameFrm, text="Device Name",width=20)
nameLbl.pack(side=LEFT,padx=5, pady=5)
nameEntry = Entry(nameFrm)
nameEntry.pack(fill=X, padx=5, pady=5)
butFrm = Frame(self)
butFrm.pack(fill=X)
opnBut = Button(butFrm, text="Open Cfg", command=openCfg)
opnBut.pack(fill=X, padx=5,pady=5)
root = Tk()
root.geometry("600x600")
app = Application(root)
app.mainloop()
items which are defined in the class namespace are bound to the class. In this case, you have a couple options...
One option is that you could make it a staticmethod:
class Application(Frame):
#staticmethod
def openCfg():
name = getNameFromFile()
nameEntry.insert(0, name)
And then bind the button as:
opnBut = Button(butFrm, text="Open Cfg", command=self.openCfg)
However, staticmethods are rarely necessary. In this case, I might just move the definition of openCfg out of the class and keep everything else as it is:
def openCfg():
name = getNameFromFile()
nameEntry.insert(0, name)
class Application(Frame):
...
On a second look, this will probably still bring up a NameError for nameEntry. You'll probably want a first-class method:
class Application(Frame):
def openCfg(self):
name = getNameFromFile()
self.nameEntry.insert(0, name)
And of course, when you create nameEntry, you'll need to make it a member of the Application class.
...
self.nameEntry = Entry(nameFrm)
self.nameEntry.pack(fill=X, padx=5, pady=5)
...

Looking for a super explanation /tkinter direction (getting max recursion depth without super)

So I'm trying to use my "controller" to call my "view." But if I don't use super, I get an infinite recursion when buildTK tries to build iiBar. Using Super everything is fine. I'd just like to understand why that is.
import inputhandler as iH
import buildtk as tA
import scanhandler as aS
class ControlHandler:
def __init__(self):
#self.view = tA.buildTK() #does not work
self.view = super(tA.buildTK) #works
self.smodel = aS.aScan()
self.imodel = iH.InputHandler()
The buildTK class:
import tkinter as tt
import controlhandler as cH
class buildTK(tt.Frame):
def __init__(self, master = None):
self.frame = tt.Frame(master, bg="tan")
self.frame.grid()
self.ibar = iiBar(self.frame)
...
class iiBar:
def __init__(self, master):
print(repr(self)) #prints forever
self.mbar = tt.Frame(master, relief = 'raised', bg="blue")
self.mbar.grid(column=0, row=0) #Show File Bar
self.tryFile()
self.tryTool()
self.tryH()
EDIT: those try methods have no effect when commented out, but the basic code is:
def tryTool(self):
# Create tools menu
self.toolsbutton = tt.Menubutton(self.mbar, text = 'Tools', )
self.toolsbutton.grid(row=0, column=2)
self.toolsmenu = tt.Menu(self.toolsbutton, tearoff=0)
self.toolsbutton['menu'] = self.toolsmenu
# Populate tools menu
self.toolsmenu.add('command', label = 'tools', command = root.destroy)
And out of curiosity, is there a best-practice for going about what I'm trying to do? Eventually I'd like a "build handler" to instantiate the form (either tkinter, html, xml) - in which case the controller would instantiate the build handler which would determine what to build.
Found my issues. Some python oversights.
the import seems to take care of the instantiation
part of this has to do with the inconsistency I used at the end of my classes, i.e;
a. #if name == "main": ControlHandler()
forgot that was commented out
b. buildTK
root = tt.Tk()
all = buildTK(root)
root.mainloop()
c. buildTK0
def main():
root = tk.Tk()
app = Application(root)
app.mainloop()
if __name__ == "__main__":main()
else: main()
Super appreciate the feedback guys! Gave me lots to consider/review!
What you show here is not a good example of inheritance - it is somehwat messed up. The same thing goes for yout attempeted uses of super - it just does not crash because you are not doing anything with the super-object at all, after creating it.
So., first, define if you are inheriting Tkinter components of compositing, having attributes of your classes that reference Tkinter objects. This code snippet:
class buildTK(tt.Frame):
def __init__(self, master = None):
self.frame = tt.Frame(master, bg="tan")
self.frame.grid()
self.ibar = iiBar(self.frame)
does a little of both.
I consider (and a lot of the internet) that trying to inherit from a complex GUI class is a waste of time and effort - although OO purists from the 90's thought that tobe a good idea and documented it that way. Tkinter classes have hundreds of methods and attributes - if you try to subclass one of those, your chances of name-clashing sky-rocket, to start with.
Otherwise, if you just don't try to inherit from any tkinter component, and just use them, and give-up on your non-use of supe, your app have a nice chance of working -
as for what "super" does: it provides a clean mean to call the method you are overriding in a sublass on its superclasses, respecting Python's method-resolution-order (mro), and without hardcoding the super-class reference inside the method. supershould be used only for that - for example, if you were to properly inherit tkinter.frame:
class buildTK(tt.Frame):
def __init__(self, master = None):
super(buildTK, self).__init__(master, bg="tan")
# this is for composition: self.frame = tt.Frame(master, bg="tan")
self.grid()
# a prefix on our attributes and methods avoid clashing with
# tkinter:
self._myapp_ibar = iiBar(self.frame)

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