sebastien deepwali
sebastien deepwali

Reputation: 29

I don't know how to use urwid.Button

Hello i'm trying to understand urwid library to make my programs:

I have a problem, when i create a button with: urwid.Button('my button', on_press=function()) or like in the code below:

import urwid

def show_or_exit(key):
    if key in ('q', 'Q'):
        raise urwid.ExitMainLoop()
   
def action():
    print("click")

button = urwid.Button(' Press Enter Key ... ')
urwid.connect_signal(button, 'click', action())
button = urwid.Padding(button, align='center', width=20)
button = urwid.Filler(button, 'middle')

mainloop = urwid.MainLoop(button, unhandled_input=show_or_exit)
mainloop.run()
  1. the function action is called when i launch the program
  2. when i click the button i have an error : TypeError: 'NoneType' object is not callable

Any idea ?

Upvotes: -2

Views: 211

Answers (1)

furas
furas

Reputation: 142651

callback means function's name without () and without arguments.

urwid.connect_signal(button, 'click', action)  # `action` without `()

And when you will press button then it will use () to execute this function.

And probably all GUIs need function's name without () and without arguments.


EDIT:

Your code works like

result = action()

urwid.connect_signal(button, 'click', result)

Because action() returns None so you have

urwid.connect_signal(button, 'click', None)

and later it will try to execute None()

And this gives TypeError: 'NoneType' object is not callable


EDIT:

There is other problem in code. urwid sends button/widget to this function and you have to get this argument

def action(widget):
    #print('widget:', widget)
    #print('label:', widget.label)
    print("click")

It sends button and you can assign function to different buttons and inside function you can access pressed button to modify it or get some parameters from button (i.e. get/set text on button).


BTW:

If you will have to use function which gets arguments then you can use lambda to create function without arguments

def action(widget, text):
    print(text)

urwid.connect_signal(button, 'click', lambda widget:action(widget, "Hello World"))

And if you will have to use for-loop to create many buttons then you may need to assign value to variable in lambda:

for numr in range(5)
    button = urwid.Button(f'Number {num}')
    urwid.connect_signal(button, 'click', lambda widget,x=num:action(widget, x))  
    # not `lambda widget:action(widget, num)`

Upvotes: 0

Related Questions