GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Mon Sep 22, 2014 4:13 am

All times are UTC




Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: Swapping images of button widgets when two buttons are click
PostPosted: Sat Nov 24, 2012 3:55 am 
Offline

Joined: Mon Nov 19, 2012 2:49 pm
Posts: 2
When I press the first button and then another, the buttons should swap the images assigned to them. Code is running on:
GCC ..MinGW Windows7(32bit).
gtk+-bundle_2.24.10-win32
I don't get any error while compiling. But I get the following error while running it.
Quote:
(a.exe:2348): Gtk-CRITICAL **: gtk_button_set_image: assertion `image == NULL || GTK_IS_WIDGET (image)' failed

How can I fix this?
Code:
#include<gtk/gtk.h>
#include<stdio.h>

static GtkWidget *prev_b; // previous button click stored here
static GtkWidget *prev_i;   // previuos button's image
static int count=0;  //distinguish between two button's click
GtkWidget *button1,*button2; //global button widget
GtkWidget *img1; //global image widget1
GtkWidget *img2;   // global image widget2
   
static void on_click(GtkWidget * button, GtkWidget *b);

int main(int argc , char *argv[])
   {
   GtkWidget * window;
   GtkWidget * hbox;

   gtk_init(&argc,&argv);
   button1=gtk_button_new_with_label("");
   button2=gtk_button_new_with_label("");
   img1=gtk_image_new_from_file("img/other/h6.png");
   img2=gtk_image_new_from_file("img/other/h7.png");
   window=gtk_window_new(GTK_WINDOW_TOPLEVEL);
   hbox=gtk_hbox_new(TRUE,5);
   
   gtk_button_set_image(GTK_BUTTON(button1),img1);
   gtk_button_set_image(GTK_BUTTON(button2),img2);
   gtk_box_pack_start_defaults(GTK_BOX(hbox),button1);
   gtk_box_pack_start_defaults(GTK_BOX(hbox),button2);
   
   gtk_container_add(GTK_CONTAINER(window),hbox);
   gtk_widget_show_all(window);
   gtk_widget_show(img1);
   gtk_widget_show(img2);
   
   g_signal_connect(G_OBJECT(button1),"clicked",G_CALLBACK(on_click),img1);
   g_signal_connect(G_OBJECT(button2),"clicked",G_CALLBACK(on_click),img2);
   g_signal_connect(G_OBJECT(window), "destroy",G_CALLBACK(gtk_main_quit), NULL);
   
   gtk_main();   
   return 0;
   }
   
static void on_click(GtkWidget * button, GtkWidget *img)
   {
      GtkWidget *temp;
      temp=gtk_image_new_from_file("img/other/temp.png");
      gtk_widget_show(temp);
   
      if(count==1)
         {   count=count-1;
            if(prev_i==img)return;
            else
            {   
            gtk_button_set_image(GTK_BUTTON(prev_b),temp); //setting image to prev button
            gtk_button_set_image(GTK_BUTTON(button),prev_i);//setting image to current button
            gtk_button_set_image(GTK_BUTTON(prev_b),img);//setting image to current button
            }
            return ;
         }
      if(count==0)
         {
            count=count+1;
            prev_b=button;
            prev_i=img;
            return ;
         }
}


Top
 Profile  
 
 Post subject: Re: Swapping images of button widgets when two buttons are c
PostPosted: Sat Nov 24, 2012 7:24 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 746
Location: UK
Hello,

When you call gtk_button_set_image() any existing image that is stored there is dereferenced. If the reference count becomes 0 then it is deallocated. In your case the pointers img1 and img2 become invalid due to being deallocated, which is the cause of your errors.

Your code seams over complex for what should be a simple bit of code. I would revisit what the code needs to do then work on the implementation.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Swapping images of button widgets when two buttons are c
PostPosted: Sat Nov 24, 2012 7:55 am 
Offline
Never Seen the Sunlight

Joined: Thu Mar 24, 2011 2:10 pm
Posts: 328
Location: Sydney, Australia
Ah Errol you beat me to it. Well confirmation of what I was writing is good. Here's what I already had prepared:

#1 gtk_button_set_image like many things calls gtk_container_remove which decreases the reference count of the widget being removed meaning it may destroy the widget when doing so. I think this might be why you are having your runtime error (widget destroyed means GTK_IS_WIDGET fails but the pointer still exist so ==NULL also fails). In order to preserve the widget being removed you generally need to bracket such functions with g_object_ref and g_object_unref. Take a look at some of the tutorials on reference counting. In this new scheme you won't have to set up a temporary image (using NULL would have worked even if you did).
#2 you are going about this the wrong way. You might get the buttons to be able to swap like this, but you won't be able to get them to swap back. You have signal connected button1 with img1 in the data; forever tying it to button1 in the eyes of the callback (by the way the callback should have gpointer as the type for the data, not GtkWidget* but this is likely not the cause of your problems). You should keep the data as NULL and determine which is the current image by gtk_button_get_image or more efficiently by a global flag variable that keeps track of what is where. In this case you won't need prev_i and your if (prev_i==img) would be if (prev_b==button).
#3 you don't need to call widget_show on your GtkImages, this is already inherent in doing set_image.
Furthermore just as a suggestion, if you use mouse click and release events you could do the interchanging without need of the count variable. Depends if you prefer a drag and drop style though.


Top
 Profile  
 
 Post subject: Re: Swapping images of button widgets when two buttons are c
PostPosted: Sat Nov 24, 2012 9:59 am 
Offline

Joined: Mon Nov 19, 2012 2:49 pm
Posts: 2
First of all thank you for the reply..Your answer is very satisfying ..I am reading more information on reference counting now ...

@errol..thanks for valuable reply


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 4 posts ] 

All times are UTC


Who is online

Users browsing this forum: No registered users and 3 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group