[Urwid] Difference between SimpleListWalker and PollingListWalker in Frame body?

Jacob Courtneay jacob at sporkexec.com
Sun Aug 28 21:45:53 EDT 2011


I'm trying to make the footer of a Frame display different widgets when it 
receives an alarm. I'd prefer to put this logic in the footer widget itself 
rather than using Frame.set_footer to keep the frame code simple (although maybe 
this should be reconsidered).

The way I've done this, the footer may fail to render the changes depending on 
the body widget. I can't figure out why, but I suspect something to do with 
canvas caching.

I've discovered that subclassing WidgetWrap instead of hacking my own wrapper 
fixes it (so I'll use that instead), but I want to understand how my first try 
failed so I can avoid it in the future. Any insight to this would be greatly 

-- Jacob

#!/usr/bin/env python2
from urwid import (Frame, SimpleListWalker, PollingListWalker, ListBox, Text,

class ToggleFrame(Frame):
    """Press 'tab' to switch bodies."""
    def __init__(self):
        self.body1 = ListBox(SimpleListWalker((Text('Fails to redraw'),)))
        self.body2 = ListBox(PollingListWalker((Text('Expected behavior'),)))
        # Same as: self.body2 = ListBox((Text('Expected behavior'),))
        self.footer = Footer()
        super(ToggleFrame, self).__init__(self.body1, footer=self.footer)

    def keypress(self, size, key):
        if key == 'tab':
            if self.get_body() is self.body1:
            elif self.get_body() is self.body2:
            return key

class Footer(object):
    """Masquerade as another widget, switching on an alarm."""
    def __init__(self):
        self.one = Text('one')
        self.two = Text('two')
        self.current = self.one

    def switch(self, loop, *args):
        if self.current is self.one:
            self.current = self.two
        elif self.current is self.two:
            self.current = self.one
        #loop.draw_screen() # Doesn't make any difference
        loop.set_alarm_in(0.5, self.switch)

    def __getattr__(self, attr):
        """We would normally use WidgetWrap for this kind of thing."""
        return getattr(self.current, attr)

frame = ToggleFrame()
loop = MainLoop(frame)
loop.set_alarm_in(0.5, frame.footer.switch) # Footer toggles itself after this.

More information about the Urwid mailing list