pythonclasssubclassttkttkwidgets

How to create a subclass of ttk.Button correctly (class function doesnt work)?


I want to create Buttons with a text and define a function that prints me the text on the monitor when i press the button.

Everything works well without classes:

from tkinter import *
from tkinter import ttk

def PressButton():
    print(FirstButton.cget('text'))

root = Tk()
root.title("Simple Calculator")

ButtonsFrame = ttk.Frame(root,relief= "groove").grid()
FirstButton=ttk.Button(ButtonsFrame, text=1, command= PressButton)
FirstButton.grid()

root.mainloop()

"1" is printed on the monitor when I press FirstButton. Because I want to have a lot of Buttons, I created a class MyButton with the parent ttk.Button:

from tkinter import *
from tkinter import ttk

class MyButton(ttk.Button):
    def __init__(self, text):
        self.text=text
        super().__init__()
        self.Button=ttk.Button(ButtonsFrame, text=self.text, command=self.PressButton)
    def PressButton(self):
        print(self.Button.cget('text'))

root = Tk()
root.title("Simple Calculator")

ButtonsFrame = ttk.Frame(root,relief= "groove").grid()
FirstButton=MyButton(1)
FirstButton.grid()

root.mainloop()

Here a button is created but without text at all. I found out that if I change the super().__init__() to super()._init__(text=self.text) then I get a Button with the right text but the PressButton command doesnt work. I tried diffent things with *args aswell but had no success.

What am I doing wrong? I would appreciate any help.


Solution

  • The main problem is that you're not specifying the parent widget for the parent in the constructor.

    Here's corrected version of code:

    from tkinter import *
    from tkinter import ttk
    
    class MyButton(ttk.Button):
        def __init__(self, parent, text):
            self.text=text
            super().__init__(parent, text=self.text, command=self.PressButton)
        def PressButton(self):
            print(self.cget('text'))
    
    root = Tk()
    root.title("Simple Calculator")
    
    ButtonsFrame = ttk.Frame(root,relief= "groove").grid()
    FirstButton=MyButton(ButtonsFrame, 1)
    FirstButton.grid()
    
    root.mainloop()
    

    You could've also swapped super(). with this:

    super(MyButton,self).__init__(parent, text=self.text,command=self.PressButton)
    

    Which is equal to super().__init__(parent, text=self.text, command=self.PressButton)

    You can read more about it here: https://docs.python.org/3/library/functions.html#super