tags:

views:

367

answers:

2

I want to change the image on GtkImage when user click a buttion, so I tried the code below, but it doesn't work.

/*
 * Compile me with:
 *   gcc -o tut tut.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
 */

#include <gtk/gtk.h>


G_MODULE_EXPORT gboolean on_button1_clicked(
       GtkWidget      *event_box,
                            GdkEventButton *event,
                            gpointer     data)
{
    GtkImage *image;
    image = GTK_IMAGE(data);
    g_return_val_if_fail(image, FALSE);

    g_object_set(image, "file","/home/2.png", NULL);
    g_print ("Event box clicked at coordinates %f,%f\n",
             event->x, event->y);
    /* Returning TRUE means we handled the event, so the signal
     * emission should be stopped (don't call any further
     * callbacks that may be connected). Return FALSE
     * to continue invoking callbacks.
     */
    return TRUE;
}
int
main( int    argc,
      char **argv )
{
    GtkBuilder *builder;
    GtkWidget  *window;
    GtkWidget  *image;
    GError     *error = NULL;

    /* Init GTK+ */
    gtk_init( &argc, &argv );


    /* Create new GtkBuilder object */
    builder = gtk_builder_new();
    /* Load UI from file. If error occurs, report it and quit application.
     * Replace "tut.<b style="color:black;background-color:#ffff66">glade</b>" with your saved project. */
    if( ! gtk_builder_add_from_file( builder, "tut_3.xml", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }

    /* Get main window pointer from UI */
    GtkImage image = GTK_WIDGET(gtk_builder_get_object(builder, "image1"));

    /* Connect signals */
    gtk_builder_connect_signals( builder, data->image);

    /* Destroy builder, since we don't need it anymore */
    g_object_unref( G_OBJECT( builder ) );

    /* Show window. All other widgets are automatically shown by GtkBuilder */
    gtk_widget_show( data->window );

    /* Start main loop */
    gtk_main();

    return( 0 );
}
+1  A: 

There's no need to use a GtkEventBox to catch the button being clicked -- just connect to the "clicked" signal of GtkButton.

Here is a version of your code that I think does what you want.

/*
 * Compile me with:
 *   gcc -o tut tut.c $(pkg-config --cflags --libs gtk+-2.0 gmodule-2.0)
 */

#include <gtk/gtk.h>


G_MODULE_EXPORT gboolean on_button1_clicked(
                        GtkButton *button,
                        gpointer     data)
{
    GtkImage *image;
    image = GTK_IMAGE(data);
    g_return_val_if_fail(image, FALSE);

    g_object_set(image, "file","icon2.png", NULL);
    g_print ("Button clicked\n");
}
int
main( int    argc,
      char **argv )
{
    GtkBuilder *builder;
    GtkWidget  *window;
    GtkWidget  *image;
    GError     *error = NULL;

    /* Init GTK+ */
    gtk_init( &argc, &argv );


    /* Create new GtkBuilder object */
    builder = gtk_builder_new();
    /* Load UI from file. If error occurs, report it and quit application.
     * Replace "tut.<b style="color:black;background-color:#ffff66">glade</b>" with your saved project. */
    if( ! gtk_builder_add_from_file( builder, "tut_3.xml", &error ) )
    {
        g_warning( "%s", error->message );
        g_free( error );
        return( 1 );
    }

    /* Get main window pointer from UI */
    window = GTK_WIDGET(gtk_builder_get_object(builder, "window1"));
    image = GTK_WIDGET(gtk_builder_get_object(builder, "image1"));

    /* Connect signals */
    gtk_builder_connect_signals( builder, image);

    /* Destroy builder, since we don't need it anymore */
    g_object_unref( G_OBJECT( builder ) );

    /* Show window. All other widgets are automatically shown by GtkBuilder */
    gtk_widget_show( window );

    /* Start main loop */
    gtk_main();

    return( 0 );
}

And here is the corresponding Glade file:

<?xml version="1.0"?>
<interface>
  <requires lib="gtk+" version="2.16"/>
  <!-- interface-naming-policy project-wide -->
  <object class="GtkWindow" id="window1">
    <child>
      <object class="GtkButton" id="button1">
        <property name="label" translatable="yes">button</property>
        <property name="visible">True</property>
        <property name="can_focus">True</property>
        <property name="receives_default">True</property>
        <property name="image">image1</property>
        <signal name="clicked" handler="on_button1_clicked"/>
      </object>
    </child>
  </object>
  <object class="GtkImage" id="image1">
    <property name="visible">True</property>
    <property name="pixbuf">icon1.png</property>
  </object>
</interface>

To run it, you need to put two files, icon1.png and icon2.png, in the current directory.

PS. I can't be sure exactly what your code is doing if you don't post the Glade file too. Also, your code didn't even compile, so it would have been nice if you had said exactly what didn't work.

ptomato
A: 

To add to ptomato's answer, gtk_object_set() should work, but it's kind of a roundabout way of doing things. Take a look here for a more normal API call for replacing the contents of an existing GtkImage with the contexts of a disk file.

Bob Murphy
Setting the `"file"` property is __the same__ as `gtk_image_set_from_file`.http://git.gnome.org/cgit/gtk+/tree/gtk/gtkimage.c#n340
ntd