| FAQ Index - Search - Recent Changes - Everything - Add entry |
5.6. How do I change the cursor for a certain widget?
Changing the cursor is remarkably easy in pygtk:
- You need to create a gtk.gdk.Cursor object first. It's constructor takes a gtk.gdk constant from the list at the end of this faq entry.
- To apply the cursor to a widget, you need to to use gdk.Window's (gdk, _not_ gtk) set_cursor() method (which requires the widget to have an associated X window, as per faq 3.3).
- To change it back to the default cursor, call set_cursor(None).
To change it for a button,
def realize_cb(widget):
b.window.set_cursor(watch)
b = gtk.Button()
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
b.connect("realize", realize_cb)
And to change it back to normal:
b.window.set_cursor(None)To make an invisible cursor (aka hide the cursor), you can use this code:
pix_data = """/* XPM */
static char * invisible_xpm[] = {
"1 1 1 1",
" c None",
" "};"""
color = gtk.gdk.Color()
pix = gtk.gdk.pixmap_create_from_data(None, pix_data, 1, 1, 1, color, color)
invisible = gtk.gdk.Cursor(pix, pix, color, color, 0, 0)
b.window.set_cursor(invisible)
To change it for a label, which lacks its own gdk.Window, for instance:
boat = gtk.gdk.Cursor(gtk.gdk.BOAT) b = gtk.EventBox() l = gtk.Label() b.add(l) b.window.set_cursor(boat)Note that the widget may already define a cursor: for instance, GtkEntry defines an I-bar for the cursor. X allows you to set a cursor on each gdk.Window, and if a window doesn't have a cursor associated with it, it gets the parent window's cursor.
To change the cursor for all the widgets, you'd need to recurse into all child widgets and set_cursor() on their gdk.Windows.
However, there is an other way, that can be implemented using some gdk.Window functions. For details, read: [www.daa.com.au]
It is also worth noticing that some widgets are composed of multiple X windows. gtk.Entry is an example -- see FAQ 14.3 (you can use the gdk.Window's children() method to get its child windows). Another example is TextView, described in FAQ 14.15.
The constants for icons defined in gtk.gdk are:
X_CURSOR ARROW BASED_ARROW_DOWN BASED_ARROW_UP BOAT BOGOSITY BOTTOM_LEFT_CORNER BOTTOM_RIGHT_CORNER BOTTOM_SIDE BOTTOM_TEE BOX_SPIRAL CENTER_PTR CIRCLE CLOCK COFFEE_MUG CROSS CROSS_REVERSE CROSSHAIR DIAMOND_CROSS DOT DOTBOX DOUBLE_ARROW DRAFT_LARGE DRAFT_SMALL DRAPED_BOX EXCHANGE FLEUR GOBBLER GUMBY HAND1 HAND2 HEART ICON IRON_CROSS LEFT_PTR LEFT_SIDE LEFT_TEE LEFTBUTTON LL_ANGLE LR_ANGLE MAN MIDDLEBUTTON MOUSE PENCIL PIRATE PLUS QUESTION_ARROW RIGHT_PTR RIGHT_SIDE RIGHT_TEE RIGHTBUTTON RTL_LOGO SAILBOAT SB_DOWN_ARROW SB_H_DOUBLE_ARROW SB_LEFT_ARROW SB_RIGHT_ARROW SB_UP_ARROW SB_V_DOUBLE_ARROW SHUTTLE SIZING SPIDER SPRAYCAN STAR TARGET TCROSS TOP_LEFT_ARROW TOP_LEFT_CORNER TOP_RIGHT_CORNER TOP_SIDE TOP_TEE TREK UL_ANGLE UMBRELLA UR_ANGLE WATCH XTERM CURSOR_IS_PIXMAPAlso if you plan to do anything time consuming and want to use the watch cursor you have to be careful that you don't starve the gui thread before it can change the cursor, e.g.
## This Will Not Work ## watch = gtk.gdk.Cursor(gtk.gdk.WATCH) gtk_window.set_cursor(watch) time.sleep(10) # your time consuming operation here gtk_window.set_cursor(None)instead call the time consuming in an idle callback (or in a different thread if you absolutely have to)...
def idle_cb(gtk_window):
time.sleep(10) # your time consuming operation here
gtk_window.set_cursor(None)
watch = gtk.gdk.Cursor(gtk.gdk.WATCH)
gtk_window.set_cursor(watch)
gobject.idle_add(idle_cb, gtk_window)
