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

Ian Ward ian at excess.org
Mon Sep 5 17:12:12 EDT 2011


Jacob Courtneay wrote on 2011-08-28 21:45:
> 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.

It is a caching issue.  It's the reason that WidgetWrap and others
"return CompositeCanvas(canv)"  in their render() definition.

Canvas objects point back to the widget that rendered them with a bit of
widget metaclass magic, but in your code you're returning the exact
canvas that was returned by the Text widget.  So even if you inherited
from urwid.Widget and called self._invalidate(), none of the caches
canvases would be marked dirty and so the screen won't redraw itself.

I do have a plan to remove all the metaclass magic and mysterious
caching and replace it with something simpler.  Not sure when exactly,
though.

Using WidgetWrap is a good solution for now.  You could also use any of
the decorations in such a way that they don't change what is displayed,
like an AttrMap(w, {}).  I've thought about adding a decoration widget
that officially does nothing for this sort of thing
(InvisibleDecoration?  NoOpDecoration?  WidgetPlaceholder?  hmm..).

Ian



More information about the Urwid mailing list