Sample code usable Tkinter listbox

Alf P. Steinbach alfps at start.no
Mon Mar 1 04:57:32 CET 2010


* rantingrick:
> On Feb 28, 6:30 pm, "Alf P. Steinbach" <al... at start.no> wrote:
>> In case Someone Else(TM) may need this.
>>
>> This code is just how it currently looks, what I needed for my code, so it's not
>> a full-fledged or even tested class.
> 
> Thanks for sharing Alf,
> Thats works fine "as-is" but what about inheriting from "tk.Listbox"
> directly and having the "container frame" as an attribute? I prefer
> this API because I hate to write the laborious
> "megawidget.mainwidget.methodX()" when i could instead write
> "megawidget.methodX()". What is your opinion on this?

Well the frame contains a listbox and scrollbar. And with the frame as attribute 
the object that you have a direct reference to would then not be the complete 
thing on screen, with respect to sizing and placement and such. I generally 
don't like widgets that present stuff outside their bounding box. I guess that 
could be fixed up somehow by overriding this and that, but I find it simpler to 
just make the enclosing widget the widget that one has a reference to. And in a 
way it's also good that it's more laborious to directly access the tkinter 
listbox stuff, because what I discovered so far is that much of it requires work 
arounds and fixups, i.e. that it should be wrapped in higher level methods.

I had to add some more such functionality after I posted that code.

So, current (this is untested except that it works for what I'm using it for!):


<code language="Py3">
class UsableListbox( t.Frame ):
     def __init__( self, parent_widget ):
         t.Frame.__init__( self, parent_widget )
         scrollbar = t.Scrollbar( self, orient = "vertical" )
         self.lb = t.Listbox( self, exportselection = 0, yscrollcommand = 
scrollbar.set )
         scrollbar.config( command = self.lb.yview )
         scrollbar.pack( side = "right", fill = "y" )
         self.lb.pack( side = "left", fill = "both", expand = 1 )

     def current_index( self ):
         indices = self.lb.curselection()
         assert( len( indices ) <= 1 )       # TODO: about multi-selection.
         return None if len( indices ) == 0 else int( indices[0] )

     def current( self ):
         #return self.lb.get( "active" )     # Incorrect with mousing
         i = self.current_index()
         return "" if i is None else self.lb.get( i )

     def item_count( self ):
         return self.lb.size()

     def clear( self ):
         self.lb.delete( 0, "end" )

     def append( self, item ):
         return self.lb.insert( "end", item )

     def select_item( self, i ):
         assert( 0 <= i < self.item_count() )
         self.lb.selection_set( i )

     def add_selection_event_handler( self, handler ):
         "An event handler takes one argument, a Tkinter Event"
         return self.lb.bind( "<<ListboxSelect>>", handler )
</code>


Cheers,

- Alf



More information about the Python-list mailing list