18 Sep

Have you ever wanted to change the drag icon on a GTK TreeView control using Python? This sounds really easy, but in fact there is a trick to getting it to work correctly. Hopefully you have found this blog prior to spending 7 days searching for a solution (like I did).

I have posted a fully working example program below, that will demonstrate how to successfully change the icon used during a drag operation. Pay close attention to way the drag_begin signal is connected (hint: that's the trick). Also, for this example to work, you must change the image path to point at a valid JPG or PNG image on your computer.

Hopefully the world is a better place now that I've shared this example. Good luck!

# import the gtk library
import gtk

# signal handler for the tree drag begin signal
# change the drag icon to a JPG as soon as the drag starts
# *** BE SURE TO CONNECT THIS EVENT WITH THE "CONNECT_AFTER(" SYNTAX ***
# *** THE ICON WILL NOT CHANGE UNLESS THIS METHOD IS USED TO CONNECT ***
def on_drag_begin(widget, context):
print "Drag Begin"

# Get a pixbuf of an image (i.e. JPG). This will be your icon.
play_image = gtk.image_new_from_file("glade/icons/jpg/arrow.jpg")
mypixbuf = play_image.get_pixbuf()

# Change the icon to the pixbuf (i.e. the JPG)
context.set_icon_pixbuf(mypixbuf, 10, 10)

# add tree to window
myTree = gtk.TreeView()

# Enable drag and drop on the treeview. If you don't call this method,
# the tree won't allow you to drag anything
myTree.enable_model_drag_source(gtk.gdk.BUTTON1_MASK, [('text/plain', 0, 0)], gtk.gdk.ACTION_DEFAULT | gtk.gdk.ACTION_MOVE)

# connect the drag begin signal handler. Be sure
# to use the "connect_after" syntax and not the regular "connect".
myTree.connect_after('drag_begin', on_drag_begin)

# create a TreeStore with one string column to use as the model
myTreeStore = gtk.TreeStore(str, str)

# we'll add some data now
myTreeStore.append(None, ["Choose a Video or Audio File to Begin", ""])

# Set the treeview's data model
myTree.set_model(myTreeStore)

# create 2 TreeViewColumns to display the data
tvcolumn = gtk.TreeViewColumn('File Name')
tvcolumn1 = gtk.TreeViewColumn('Length')

# add columns to treeview
myTree.append_column(tvcolumn)
myTree.append_column(tvcolumn1)

# create a CellRendererText to render the data
cell = gtk.CellRendererText()
cell1 = gtk.CellRendererText()

# add the cell to the tvcolumn and allow it to expand
tvcolumn.pack_start(cell, True)
tvcolumn1.pack_start(cell1, True)

# set the cell "text" attribute to column 0 - retrieve text
# from that column in treestore
tvcolumn.add_attribute(cell, 'text', 0)
tvcolumn1.add_attribute(cell1, 'text', 1)

# create new window and add the treeview
window = gtk.Window()
window.add(myTree)
window.show_all()

# Start the Main loop
gtk.main()