Bobslay
Bobslay

Reputation: 3

Python Tkinter Frame Class don't recognise objects

from tkinter import ttk
import tkinter

class MainApplication(ttk.Frame):
    texty = "text"

    def __init__(self, parent, *args, **kwargs):
        tkinter.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.button1 = ttk.Button(text=MainApplication.texty, command=self.ev(self))
        self.button1.pack()

    def ev(event, self):
        print(self.button1.text)

It calls: 'MainApplication' object has no attribute 'button1'. Why?

Upvotes: 0

Views: 73

Answers (2)

Mike - SMT
Mike - SMT

Reputation: 15226

There are many problems with your code and not just your MainApplication object error.

  1. Initialize the instance with Tk() to create the root or main toplevel window.

  2. Don't call a class attribute from inside the class by trying to call the class name.

  3. Place the texty variable inside of the __init__ part of your class and make it an attribute by putting self in front of it.

  4. Maintain good indention for code to work properly so make sure your methods are in the class with 4 space indention's.

  5. Don't print self.button1.text Instead print the attribute value by printing self.texty. If you really want to print the text on the button you can use self.button1['text'] or self.button1.cget("text") to accomplish this.

  6. Assign your class to a variable so you can interact with its attributes from outside of the class if you need to.

  7. command = slef.ev(self) is passing 2 self arguments and only requires one. Do self.ev instead.


from tkinter import ttk
import tkinter

root = tkinter.Tk()

class MainApplication(ttk.Frame):

    def __init__(self, parent, *args, **kwargs):
        tkinter.Frame.__init__(self, parent, *args, **kwargs)
        self.texty = "text"
        self.parent = parent
        self.button1 = ttk.Button(text = self.texty, command= self.ev)
        self.button1.pack()

    def ev(self):
        print(self.texty) # for printing the value of the attribute
        print(self.button1['text']) # for printing the current text of the button

app = MainApplication(root)

root.mainloop()

Just incase you were trying to print the atribute from outside of the class

You can places this outside of the class to see its results.

def print_something():
    print(app.texty) # this is why we assign the class to a variable
    print(app.button1['text']) # it allows us to interact with class atributes from outside the class

Upvotes: 0

eyllanesc
eyllanesc

Reputation: 243897

In the command attribute you must pass the name of the function, you should not call the function. In your case self.ev

In addition to get the name of the variable you must use {your button}['text'] or {your button}.cget('text')

Also def ev(event, self): is not correct, the commands do not pass any parameter so you just pass the instance: self.

Note: you must always pass the instance first: def some_function(self, other params ...)

class MainApplication(ttk.Frame):
    texty = "text"

    def __init__(self, parent, *args, **kwargs):
        tkinter.Frame.__init__(self, parent, *args, **kwargs)
        self.parent = parent
        self.button1 = ttk.Button(text=MainApplication.texty, command=self.ev)
        self.button1.pack()

    def ev(self):
        print(self.button1['text']) # or self.button1.cget('text')

root = tkinter.Tk()
w = MainApplication(root)
root.mainloop()

Upvotes: 1

Related Questions