Recipe11.4.Adding Drag and Drop Reordering to a Tkinter Listbox


Recipe 11.4. Adding Drag and Drop Reordering to a Tkinter Listbox

Credit: John Fouhy

Problem

You want to use a Tkinter Listbox widget, but you want to give the user the additional capability of reordering the entries by drag-and-drop.

Solution

We just need to code the relevant functionality and bind it to the Tkinter event corresponding to the "drag" mouse gesture:

import Tkinter class DDList(Tkinter.Listbox):     """ A Tkinter listbox with drag'n'drop reordering of entries. """     def _ _init_ _(self, master, **kw):         kw['selectmode'] = Tkinter.SINGLE         Tkinter.Listbox._ _init_ _(self, master, kw)         self.bind('<Button-1>', self.setCurrent)         self.bind('<B1-Motion>', self.shiftSelection)         self.curIndex = None     def setCurrent(self, event):         self.curIndex = self.nearest(event.y)     def shiftSelection(self, event):         i = self.nearest(event.y)         if i < self.curIndex:             x = self.get(i)             self.delete(i)             self.insert(i+1, x)             self.curIndex = i         elif i > self.curIndex:             x = self.get(i)             self.delete(i)             self.insert(i-1, x)             self.curIndex = i

Discussion

Here is an example of use of this DDList class, presented, as usual, with a guard of if _ _name_ _ == '_ _main_ _' so we can make it part of the module containing the class and have it run when the module is executed as a "main script":

if _ _name_ _ == '_ _main_ _':     tk = Tkinter.Tk( )     length = 10     dd = DDList(tk, height=length)     dd.pack( )     for i in xrange(length):         dd.insert(Tkinter.END, str(i))     def show( ):         ''' show the current ordering every 2 seconds '''         for x in dd.get(0, Tkinter.END):             print x,         print         tk.after(2000, show)     tk.after(2000, show)     tk.mainloop( )

Allowing the user of a GUI program to drag the elements of a list into new positions is often useful, and this recipe shows a fairly simple way of adding this functionality to a Tkinter Listbox widget.

This recipe's code tries to ensure that the clicked-on element stays selected by deleting and inserting on either side of it. Nevertheless, it is possible, by moving the mouse quickly enough, to start dragging an unselected element instead. While it doesn't cause any major problems, it just looks a bit odd.

This recipe's code is partly based on a post by Fredrik Lundh, http://mail.python.org/pipermail/python-list/1999-May/002501.html.

See Also

Information about Tkinter can be obtained from a variety of sources, such as Fredrik Lundh, An Introduction to Tkinter (PythonWare: http://www.pythonware.com/library), New Mexico Tech's Tkinter Reference (http://www.nmt.edu/tcc/help/lang/python/docs.html), Python in a Nutshell, and various other books.



Python Cookbook
Python Cookbook
ISBN: 0596007973
EAN: 2147483647
Year: 2004
Pages: 420

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net