[Urwid] Re: newbie looks for more examples

Fabian Braennstroem f.braennstroem at gmx.de
Thu Aug 24 14:51:02 EDT 2006

Hi Ian,

* Ian Ward <ian at excess.org> wrote:
> Fabian Braennstroem wrote:
>> Hi,
>> I just found urwid and would like to use it to adjust the
>> curses-based 'lfm' (last file manager) with some radio and
>> check buttons. It would be nice, if anybody can send me some
>> simple examples.  I am still a python newbie and I saw the
>> examples in the urwid installation directory, but as more
>> 'understandable' scripts I read the better I get into it :-)
> Have you followed the tutorial and checked out the contributed examples 
> on the web site?
Yes, but as I wrote, I am kind of new using python... and
try to copy and past a lot of interesting lines to get my
ideas to work. Python works pretty good this way; I just
import the needed module and use some lines from other
tutorials, which hopefully works. It actually does for some
small things :-)
> More simple examples would be nice, and the docs and examples can always 
> be improved on. Please please post any questions you have to the list.

Thanks! As written above, I try to 'enhance' lfm for my
needs, e.g.  printing, burning
files, making plots, converting images, running latex,... but I am missing some
radio/check buttons. Now, I tried to include the 'dialog.py' example into lfm,
just to run a 'do_msgbox'. To achive that I included the following part:

class DialogExit(Exception):

class DialogDisplay:
   palette = [
      ('body','black','light gray', 'standout'),
      ('border','black','dark blue'),
      ('selectable','black', 'dark cyan'),
      ('focus','white','dark blue','bold'),
      ('focustext','light gray','dark blue'),
   def __init__(self, text, height, width, body=None):
      width = int(width)
      if width <= 0:
         width = ('relative', 80)
      height = int(height)
      if height <= 0:
         height = ('relative', 80)
      self.body = body
      if body is None:
         # fill space with nothing
         body = urwid.Filler(urwid.Divider(),'top')

      self.frame = urwid.Frame( body, focus_part='footer')
      if text is not None:
         self.frame.header = urwid.Pile( [urwid.Text(text),
            urwid.Divider()] )
      w = self.frame
      # pad area around listbox
      w = urwid.Padding(w, ('fixed left',2), ('fixed right',2))
      w = urwid.Filler(w, ('fixed top',1), ('fixed bottom',1))
      w = urwid.AttrWrap(w, 'body')
      # "shadow" effect
      w = urwid.Columns( [w,('fixed', 2, urwid.AttrWrap(
         urwid.Filler(urwid.Text(('border','  ')), "top")
      w = urwid.Frame( w, footer = 
         urwid.AttrWrap(urwid.Text(('border','  ')),'shadow'))

      # outermost border area
      w = urwid.Padding(w, 'center', width )
      w = urwid.Filler(w, 'middle', height )
      w = urwid.AttrWrap( w, 'border' )
      self.view = w

   def add_buttons(self, buttons):
      l = []
      for name, exitcode in buttons:
         b = urwid.Button( name, self.button_press )
         b.exitcode = exitcode
         b = urwid.AttrWrap( b, 'selectable','focus' )
         l.append( b )
      self.buttons = urwid.GridFlow(l, 10, 3, 1, 'center')
      self.frame.footer = urwid.Pile( [ urwid.Divider(),
         self.buttons ], focus_item = 1)

   def button_press(self, button):
      raise DialogExit(button.exitcode)

   def main(self):
      self.ui = urwid.raw_display.Screen()
      self.ui.register_palette( self.palette )
      return self.ui.run_wrapper( self.run )

   def run(self):
      size = self.ui.get_cols_rows()
         while True:
            canvas = self.view.render( size, focus=True )
            self.ui.draw_screen( size, canvas )
            keys = None
            while not keys: 
               keys = self.ui.get_input()
            for k in keys:
               if urwid.is_mouse_event(k):
                  event, button, col, row = k
                  self.view.mouse_event( size, 
                     event, button, col, row,
               if k == 'window resize':
                  size = self.ui.get_cols_rows()
               k = self.view.keypress( size, k )

               if k:
                  self.unhandled_key( size, k)
      except DialogExit, e:
         return self.on_exit( e.args[0] )
   def on_exit(self, exitcode):
      return exitcode, ""

   def unhandled_key(self, size, key):

def do_msgbox(text, height, width):
   d = DialogDisplay( text, height, width )
   d.add_buttons([   ("OK", 0) ])
   return d

I called the 'do_msgbox' with:

    ord('U'): 'do_msgbox("test",10,15)',

which means, as soon as you type 'U' call 'do_msgbox'. This is the way I added
the other 'features'. Unfortunately, I get:

node1~/HOME$ lfm                                                                                                                            [24 Aug 8:36pm]
Traceback (most recent call last):
  File "/home/fab/Desktop/lfm/lfm.py", line 893, in ?
  File "/home/fab/Desktop/lfm/lfm.py", line 882, in lfm_start
    path = curses.wrapper(main, paths, prefs)
  File "/usr/lib/python2.4/curses/wrapper.py", line 44, in wrapper
    return func(stdscr, *args, **kwds)
  File "/home/fab/Desktop/lfm/lfm.py", line 801, in main
    ret = app.run()
  File "/home/fab/Desktop/lfm/lfm.py", line 174, in run
    ret = self.act_pane.manage_keys()
  File "/home/fab/Desktop/lfm/lfm.py", line 555, in manage_keys
    ret = actions.do(self.act_tab, ch)
  File "/home/fab/Desktop/lfm/actions.py", line 189, in do
  File "<string>", line 1, in ?
AttributeError: DialogDisplay instance has no __call__ method

Right now, I have no clue, what the last line means. Maybe, it is a simple
python/urwid problem and you do not have to know the whole lfm code to give
some tips!? Would be nice to use urwid for it.


More information about the Urwid mailing list