Example 3

A simple example that shows toggle buttons is shown below.

GTK

The file using the C language bindings to GTK to make this interface layout into a functioning program is below.

/* This program displays a couple checkboxes and shows how to change
 * button labels, how to make widgets sensitive or unsensitive, how to
 * determine if a checkbox is active, how to provide access keys for
 * quick keyboard navigation, how to pass other widgets to callbacks
 * besides the one that receives the event, and how to manually get
 * gtk+ to update widgets without returning to the main event loop.
 */

#include <gtk/gtk.h>
#include <glade/glade.h>

void
quit_handler (gpointer user_data, GtkWidget *widget)
{
  /* If the user checked the OohTellMe button, we need to do some work... */
  GtkWidget * ooh_tell_me = (GtkWidget*) user_data;
  if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (ooh_tell_me)))
    {
      /* Change the checkbutton's label */
      gtk_button_set_label (GTK_BUTTON (ooh_tell_me),
                            "M_ock me");

      /* Since we don't return to the main event loop, we have to manually tell
       * gtk+ to process the gtk_button_set_label change (and any other changes
       * that require processing).
       */
      while (g_main_context_iteration (NULL, FALSE))
        ;

      /* Mock the user and give them some time to notice the change */
      printf ("Ha ha, you fell for it!  ");
      printf ("I will not tell you what that checkbutton does!\n");
      sleep (1);
    }

  gtk_main_quit ();
}

/* delete_handler merely calls quit_handler (it is needed because this
 * callback has a different number of parameters than quit_handler)
 */
gboolean
delete_handler (gpointer user_data, GdkEvent *event, GtkWidget *widget)
{
  quit_handler(user_data, widget);

  /* We have fully handled the signal */
  return TRUE;
}

void
sensitivity_toggled (gpointer user_data, GtkWidget *widget)
{
  gtk_widget_set_sensitive ((GtkWidget*) user_data, 
                            gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
}

int
main (int argc, char *argv[])
{
  GladeXML *main_window;
  GtkWidget *widget, *ooh_tell_me;

  gtk_init (&argc, &argv);

  /* load the interface */
  main_window = glade_xml_new ("example-3.glade", NULL, NULL);

  /* connect the signals for the interface */
  ooh_tell_me = glade_xml_get_widget (main_window, "OohTellMe");
  widget      = glade_xml_get_widget (main_window, "SensitivityCheckButton");
  g_signal_connect_swapped (G_OBJECT (widget), "clicked",
                            G_CALLBACK (sensitivity_toggled),
                            G_OBJECT (ooh_tell_me));

  widget = glade_xml_get_widget (main_window, "OptionWindow");
  g_signal_connect_swapped (G_OBJECT (widget), "delete_event",
                            G_CALLBACK (delete_handler),
                            G_OBJECT (ooh_tell_me));

  widget = glade_xml_get_widget (main_window, "QuitButton");
  g_signal_connect_swapped (G_OBJECT (widget), "clicked",
                            G_CALLBACK (quit_handler),
                            G_OBJECT (ooh_tell_me));

  /* start the event loop */
  gtk_main ();

  return 0;
}

GTKMM

The files using the C++ language bindings to GTK to make this interface layout into a functioning program are below. First, the ExampleWindow.h header file:

#ifndef EXAMPLEWINDOW_H
#define EXAMPLEWINDOW_H

#include <libglademm.h>
#include <gtkmm.h>

class ExampleWindow : public Gtk::Window
{
public:
  ExampleWindow(BaseObjectType* cobject,
                const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml);
  virtual ~ExampleWindow();

protected:
  virtual bool on_delete_event(GdkEventAny* event);
  void         time_to_quit();
  void         sensitivity_toggled();

  Gtk::CheckButton* d_sensitivity_check_button;
  Gtk::CheckButton* d_ooh_tell_me;
  Gtk::Button*      d_quit_button;
};

#endif // EXAMPLEWINDOW_H

Next is the ExampleWindow.cc file:

#include "ExampleWindow.h"
#include <iostream>

using namespace std;

ExampleWindow::ExampleWindow(
  BaseObjectType* base_object,
  const Glib::RefPtr<Gnome::Glade::Xml>& glade_xml)
  : Gtk::Window(base_object)
{
  // Get the necessary widgets
  glade_xml->get_widget("SensitivityCheckButton", d_sensitivity_check_button);
  glade_xml->get_widget("OohTellMe",              d_ooh_tell_me);
  glade_xml->get_widget("QuitButton",             d_quit_button);

  // Connect the appropriate callbacks...
  d_sensitivity_check_button->signal_toggled().connect(
    sigc::mem_fun(*this, &ExampleWindow::sensitivity_toggled) );
  d_quit_button->signal_clicked().connect( 
    sigc::mem_fun(*this, &ExampleWindow::time_to_quit) );
}

ExampleWindow::~ExampleWindow()
{
}

void
ExampleWindow::sensitivity_toggled()
{
  d_ooh_tell_me->set_sensitive( d_sensitivity_check_button->get_active() );
}

void
ExampleWindow::time_to_quit()
{
  // If the user checked the OohTellMe button, we need to do some work...
  if (d_ooh_tell_me->get_active()) {

    // Change the checkbutton's label
    d_ooh_tell_me->set_label("M_ock me");

    /* Since we don't return to the main event loop, we have to
     * manually tell gtk+ to process the set_label change (and any
     * other changes that require processing).
     */
    while (Glib::MainContext::get_default()->iteration(false))
        ;

    // Mock the user and give them some time to notice the change
    cout << "Ha ha, you fell for it!  ";
    cout << "I will not tell you what that checkbutton does!" << endl;
    sleep(1);
  }

  hide();
}

bool
ExampleWindow::on_delete_event(GdkEventAny* event)
{
  time_to_quit();

  // No other handlers need be called...
  return true;
}

And finally, here is the example-3.cc file which glues everything together:

/* This program displays a couple checkboxes and shows how to change
 * button labels, how to make widgets sensitive or unsensitive, how to
 * determine if a checkbox is active, how to provide access keys for
 * quick keyboard navigation, how to pass other widgets to callbacks
 * besides the one that receives the event, and how to manually get
 * gtkmm to update widgets without returning to the main event loop.
 */

#include <gtkmm.h>
#include <libglademm/xml.h>
#include "ExampleWindow.h"

using namespace std;

int
main (int argc, char *argv[])
{
  Glib::RefPtr<Gnome::Glade::Xml> main_window;
  Gtk::Main kit(argc, argv);

  // load the interface
  main_window = Gnome::Glade::Xml::create("example-3.glade");

  // Get the main window
  ExampleWindow* window;
  main_window->get_widget_derived("OptionWindow", window);

  // start the event loop
  Gtk::Main::run( *window );

  return 0;
}

GTK2-PERL

The file using the perl language bindings to GTK to make this interface layout into a functioning program is below.

#!/usr/bin/perl -w

# This program displays a couple checkboxes and shows how to change
# button labels, how to make widgets sensitive or unsensitive, how to
# determine if a checkbox is active, how to provide access keys for
# quick keyboard navigation, how to pass other widgets to callbacks *
# besides the one that receives the event, and how to manually get
# gtk+ to update widgets without returning to the main event loop.

use Glib qw(TRUE FALSE);
use Gtk2 '-init';
use Gtk2::GladeXML;

# Just to be pedantic...
use strict;
use vars qw($main_window);

# Unlike the C bindings for libglade, perl does not use an equivalent
# to G_CONNECT_SWAPPED when an Object is specified for a signal
# handler.  This means that the parameters are not swapped.
sub quit_handler
{
  my (undef, $tellme_widget) = @_;  # widget (quit_button) is unused

  # If the user checked the OohTellMe button, we need to do some work...
  if ($tellme_widget->get_active) {

    # Change the checkbutton's label
    $tellme_widget->set_label("M_ock me");

    # Since we don't return to the main event loop, we have to manually tell
    # gtk+ to process the gtk_button_set_label change (and any other changes
    # that require processing).
    while (Glib::MainContext->default->iteration(FALSE)) {
    }

    # Mock the user and give them some time to notice the change
    print "Ha ha, you fell for it!  ";
    print "I will not tell you what that checkbutton does!\n";
    sleep (1);
  }

  Gtk2->main_quit;
}

# Unlike the C bindings for libglade, perl does not use an equivalent
# to G_CONNECT_SWAPPED when an Object is specified for a signal
# handler.  This means that the parameters are not swapped.
sub delete_handler
{
  my ($quit_button, undef, $tellme_widget) = @_;  # event is not used
  &quit_handler($quit_button, $tellme_widget);
}

# Unlike the C bindings for libglade, perl does not use an equivalent
# to G_CONNECT_SWAPPED when an Object is specified for a signal
# handler.  This means that the parameters are not swapped.
sub sensitivity_toggled
{
  my ($sensitivity_widget, $tellme_widget) = @_;
  $tellme_widget->set_sensitive($sensitivity_widget->get_active);
}


  # load the interface
  $main_window = Gtk2::GladeXML->new('example-3.glade');

  # connect the signals in the interface
  $main_window->signal_autoconnect_from_package('main');

  # start the event loop
  Gtk2->main;

PYGTK

The file using the python language bindings to GTK to make this interface layout into a functioning program is below.

#!/usr/bin/env python

# This program displays a couple checkboxes and shows how to change
# button labels, how to make widgets sensitive or unsensitive, how to
# determine if a checkbox is active, how to provide access keys for
# quick keyboard navigation, how to pass other widgets to callbacks
# besides the one that receives the event, and how to manually get gtk
# to update widgets without returning to the main event loop.

import gtk
import gtk.glade
from time import sleep

class ExampleWindow:
  def __init__(self, glade_file):
    # Parse the glade file
    self.main_window = gtk.glade.XML(glade_file)

    # Get the necessary widgets
    self.sensitivity_check_button = \
      self.main_window.get_widget("SensitivityCheckButton")
    self.ooh_tell_me = self.main_window.get_widget("OohTellMe")
    self.quit_button = self.main_window.get_widget("QuitButton")

    # Connect the appropriate callbacks...
    self.main_window.signal_autoconnect(
      {"sensitivity_toggled" : self.sensitivity_toggled,
       "quit_handler"        : self.quit_handler,
       "delete_handler"      : self.delete_handler}
      )
    
  def sensitivity_toggled(self, widget_object):
    self.ooh_tell_me.set_sensitive( self.sensitivity_check_button.get_active() );
    
  def quit_handler(self, extra):
    # If the user checked the OohTellMe button, we need to do some work...
    if self.ooh_tell_me.get_active():

      # Change the checkbutton's label
      self.ooh_tell_me.set_label("M_ock me")

      # Since we don't return to the main event loop, we have to
      # manually tell gtk+ to process the set_label change (and any
      # other changes that require processing).  WARNING: This method
      # is actually obsolete and apparently has potential problems,
      # but I was working with an older version of pygtk and this is
      # the only way that would work.  I was too lazy to try intalling
      # a newer version that might account for the fact that the main
      # loop has moved from gtk to glib.
      while gtk.events_pending():
        gtk.main_iteration(1)

      # Mock the user and give them some time to notice the change
      print "Ha ha, you fell for it!  ",
      print "I will not tell you what that checkbutton does!"
      sleep(1)

    gtk.mainquit();
    
  def delete_handler(self,event,widget_object):
    self.quit_handler(widget_object)

    # No other handlers need be called...
    return gtk.TRUE;

# Create the ExampleWindow
window = ExampleWindow("example-3.glade")

# start the event loop
gtk.main()