Having a problem with the urwid library if anyone is familiar with it, I could use a hand. there are two code snippets below, the first one is a working example copied from the urwid documentation, the second one is the result of me frankensteining some different examples from the documentation together.
My main issue is that the item_chosen function that should run on the "click" event, i.e. pressing enter, doesn't seem to run in the second version
It's hard to find many urwid resources other than the documentation, and i haven't used it for long enough to wrap my mind fully around their widget model, my apologies if this is somehow trivial or obvious.
This is a working example copied from the urwid documentation.
import urwid
choices = u'Chapman Cleese Gilliam Idle Jones Palin'.split()
def menu(title, choices):
body = [urwid.Text(title), urwid.Divider()]
for c in choices:
button = urwid.Button(c)
urwid.connect_signal(button, 'click', item_chosen, c)
body.append(urwid.AttrMap(button, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleFocusListWalker(body))
def item_chosen(button, choice):
response = urwid.Text([u'You chose ', choice, u'\n'])
done = urwid.Button(u'Ok')
urwid.connect_signal(done, 'click', exit_program)
main.original_widget = urwid.Filler(urwid.Pile([response,
urwid.AttrMap(done, None, focus_map='reversed')]))
def exit_program(button):
raise urwid.ExitMainLoop()
main = urwid.Padding(menu(u'Pythons', choices), left=2, right=2)
top = urwid.Overlay(main, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
urwid.MainLoop(top, palette=[('reversed', 'standout', '')]).run()
I tried to refactor it into a class, with mixed success.
class Menu:
def __init__(self,title,choices):
pad = urwid.Padding(self.make(title, choices), left=2, right=2)
self.main = urwid.Overlay(pad, urwid.SolidFill(u'\N{MEDIUM SHADE}'),
align='center', width=('relative', 60),
valign='middle', height=('relative', 60),
min_width=20, min_height=9)
def make(self,title,choices):
body = [urwid.Text(title), urwid.Divider()]
for c in choices:
button = urwid.Button(c)
urwid.connect_signal(button, 'click', self.item_chosen, c)
body.append(urwid.AttrMap(button, None, focus_map='reversed'))
return urwid.ListBox(urwid.SimpleFocusListWalker(body))
def item_chosen(self, button, choice):
response = urwid.Text([u'You chose ', choice, u'\n'])
done = urwid.Button(u'Ok')
urwid.connect_signal(done, 'click', exit_program)
self.main.original_widget = urwid.Filler(urwid.Pile([response,
urwid.AttrMap(done, None, focus_map='reversed')]))
my full code here: https://pastebin.com/bv4eubiy
As i described above, and as you will notice if you run the second code, the dialog box showing you what you chose does not appear, i can't figure out why.
After much reflection on the documentation, my error is obvious.
The line self.main.original_widget = urwid.Filler(urwid.Pile([response,urwid.AttrMap(done, None, focus_map='reversed')]))
is modifying the original_widget
member of the urwid.Padding
class. In my code above I had set self.main
to be an urwid.Overlay
instead of an urwid.Padding
. moving around some objects solves the problem.