Ben
Ben

Reputation: 31

Overriding toga.Button using super()

I'm a newbie in Python and to learn more about OOP. I want to create a new button class based on toga.Button. I used the example on the Toga website and added a new class based on the toga.Button class. Initially, I would like the behaviour of this dervived class to be the same as the original class. However, when running the code I get an error.

The code is as follows:

import toga

def button_handler(widget):
    print("hello")

class ColorButton(toga.Button):
    def init(self, *args):
        super().init(*args)

    def on_press(self, *args, **kwargs):
        super().on_press(*args, **kwargs)

def build(app):
    box = toga.Box()

    button = toga.Button("Hello world", on_press=button_handler)
    button.style.padding = 50
    button.style.flex = 1
    box.add(button)
    
    button1 = ColorButton("Hello world1", on_press=button_handler)
    button1.style.padding = 50
    button1.style.flex = 1
    box.add(button1)
    
    return box

def main():
    return toga.App("First App", "org.beeware.toga.tutorial", startup=build)

if name == "main":
    main().main_loop()

Running the code give the following error:

Traceback (most recent call last): File "\\app\\ttt_main\_.py", line 4, 
in \<module\> main().main_loop() File "\\app_packages\\toga\\app.py", line 619,
in main_loop self.\_impl.main_loop() File "\\app_packages\\toga_winforms\\app.py", line 302,
in main_loop raise self.\_exception File "\\app_packages\\toga_winforms\\app.py", line 277,
in \_run_app self.create() File "\\app_packages\\toga_winforms\\app.py", line 148,
in create self.interface.\_startup() File "\\app_packages\\toga\\app.py", line 641,
in \_startup self.startup() File "\\app_packages\\toga\\app.py", line 654,
in startup self.main_window.content = self.\_startup_method(self) File "\\app\\ttt\\app.py", line 21,
in build button1 = ColorButton("Hello world1", on_press=button_handler)
TypeError: init() got an unexpected keyword argument 'on_press'

I would liked to have seen two buttons with similar behaviour.

Upvotes: 1

Views: 86

Answers (1)

oskar
oskar

Reputation: 653

Functions can take arguments and keyword arguments.
A function can take a list of arguments, when you prefix the argument with a *, e.g. *args, as you already do. This variable will hold a tuple of the collected arguments.
Similarly, a function can take keyword arguments when you prefix an argument with **, e.g. **kwargs. This variable will hold a dictionary with the keys and their associated values ("on_press" and button_handler in your case). The same applies for unpacking: tuples with * and dictionaries with **.

So your current ColorButton.__init__ method only takes arguments and no keyword arguments. It can't take arguments. If it would, the values were not associated with their keys in the args tuple.

Therefore just add **kwargs to your ColorButton.__init__ method:

class ColorButton(toga.Button):
    def init(self, *args, **kwargs):
        super().init(*args, **kwargs)

But if you don't intend to change or add anything to this method, there's no benefit in overwriting it. You can just leave it out.

Upvotes: 0

Related Questions