Hi,

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 
appreciated.

-- Jacob

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

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:
                self.set_body(self.body2)
            elif self.get_body() is self.body2:
                self.set_body(self.body1)
        else:
            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.
loop.run()
# EOF


_______________________________________________
Urwid mailing list
[email protected]
http://lists.excess.org/mailman/listinfo/urwid

Reply via email to