How to make a clickable label in Gtk2/ruby

Sometimes, you need a Gtk label, styled like a web link that opens an URL when you click. I need this widget for the todo-summarizer Gtk2 GUI and I don't like the look and feel of the Gtk LinkButton widget.

So, I wrote a custom ClickableLabel widget that handle the URL, opens your system's default web browser, shows the destination URL either in a tooltip or a status label and change the mouse cursor change when you hover it.
A clickable label used in todo-summarizer

This code was inspired by two articles written in perl/gtk2 you can found here : part1 and part2.

The main issue in this class is that Gtk::Label can't handle mouse events, so you have to use a Gtk:EventBox and use #pack_start to make the whole thing visible.

The last thing to implement is the mouse cursor change : just remember than you can only set the cursor of a Gdk::Window (not a Gtk one).

Here the complete source of this new widget :
# A clickable Gtk::Label styled as a web link
# parent:       The parent widget (or box...)
# text:         The text of the label
# uri:          The uri your browser will open if you click
# status_label: An optional label to print the destination 
#               URI when you hover the label. If no status_label 
#               is provided, URI is printed in a tooltip
class ClickableLabel < Gtk::Label
 def initialize(parent, text, uri, status_label = nil)
    super() # Avoid the 'uninitialize GLib::Object' issue
    self.set_markup("<span color=\"blue\"><u>%s</u></span>"%text)

    eb =
    eb.signal_connect('button-press-event') do
      open uri
    parent.pack_start(eb) # Make the whole thing visible

    # Do not try to change the cursor here, self.window 
    # returns nil because the widget isn't actualy created.
    eb.signal_connect('enter-notify-event') do
      if status_label
      # The default cursor is actually Gdk::Cursor::Type::ARROW
      cur =
      # Get the underlying Gdk::Window of the label and change 
      # its mouse cursor
    if status_label
      eb.signal_connect('leave-notify-event') do 


  # From
  # Should be tested
  def open(link)
    if RbConfig::CONFIG['host_os'] =~ /mswin|mingw|cygwin/
      system "start #{link}"
    elsif RbConfig::CONFIG['host_os'] =~ /darwin/
      system "open #{link}"
    elsif RbConfig::CONFIG['host_os'] =~ /linux|bsd/
      system "xdg-open #{link}"
You can use this with our without a status label to show the destination URL :
txt="My blog's URL"
# Without a status label, destination is in a tooltip, txt, uri)
# With a status label, destination is printed on mouse hover, txt, uri, status)


Popular posts from this blog

How to make a map of variant in C++