Search code examples
cgtkgtk3

initialization of GtkImage in c


I'm encountering a Segmentation Fault when I try to make a Gtkwidget point to a memory address where I've load a png from file. I want card[6].image to display the image I've loaded in card[0].image and the I'd like to remove the same image from card[0].image.

struct my_image {

    const char *path;
    GtkWidget *image;
};

void create_window() {

    GtkWidget *window;
    GtkWidget *headbar;
    GtkWidget *vbox;
    GtkWidget *hbox_3;
    GtkWidget *hbox_table;
    GtkWidget *hbox_1;
    GtkWidget *hbox_2;
    GtkWidget *about_button;
    GtkWidget *event_box1, *event_box2, *event_box3;

    window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
    headbar = gtk_header_bar_new();
    about_button = gtk_button_new_with_mnemonic("CLick");
    event_box1 = gtk_event_box_new ();
    event_box2 = gtk_event_box_new ();
    event_box3 = gtk_event_box_new ();
    vbox = gtk_box_new (GTK_ORIENTATION_VERTICAL, 50);   
    hbox_3 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 35);
    hbox_table = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 35);
    hbox_2= gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 0);
    hbox_1 = gtk_box_new (GTK_ORIENTATION_HORIZONTAL, 35);   

    gtk_header_bar_set_title (GTK_HEADER_BAR (headbar), "Myprogram");
    gtk_window_set_title (GTK_WINDOW (window), "Myprogram");    
    gtk_window_set_titlebar (GTK_WINDOW (window), headbar);
    gtk_header_bar_set_show_close_button (GTK_HEADER_BAR (headbar), TRUE);
    gtk_window_maximize (GTK_WINDOW (window));  

    card[0].path = pile[0];
    card[1].path = pile[1];
    card[2].path = pile[2];

    card[0].image = gtk_image_new_from_file (card[0].path);
    card[1].image = gtk_image_new_from_file (card[1].path);
    card[2].image = gtk_image_new_from_file (card[2].path);

    card[3].path = "c/fort.png";
    card[4].path = "c/fort.png";
    card[5].path = "c/fort.png";

    card[3].image = gtk_image_new_from_file (card[3].path);
    card[4].image = gtk_image_new_from_file (card[4].path);
    card[5].image = gtk_image_new_from_file (card[5].path);


    card[6].image = gtk_image_new ();
    card[7].image = gtk_image_new ();

    printf("card 0 address = %u\n", card[0].image);
    printf("card 6 address = %u\n", card[6].image);     

    card[8].path = pile[39];
    card[9].path = "c/mazzo.png";
    card[8].image = gtk_image_new_from_file (card[8].path);
    card[9].image = gtk_image_new_from_file (card[9].path);

    g_signal_connect (about_button, "clicked", G_CALLfort (activate_about), NULL);
    g_signal_connect (G_OBJECT (event_box1), "button_press_event", G_CALLfort (card1_clicked), card);
    g_signal_connect (G_OBJECT (event_box2), "button_press_event", G_CALLfort (card2_clicked), card);
    g_signal_connect (G_OBJECT (event_box3), "button_press_event", G_CALLfort (card3_clicked), card);
    g_signal_connect (G_OBJECT (window), "destroy", G_CALLfort (destroy), NULL);

    gtk_container_add(GTK_CONTAINER (headbar), about_button);
    gtk_container_add(GTK_CONTAINER (window), vbox);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_3);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_table);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_2);
    gtk_container_add(GTK_CONTAINER (vbox), hbox_1);
    gtk_container_add(GTK_CONTAINER (hbox_2), card[8].image);
    gtk_container_add(GTK_CONTAINER (hbox_2), card[9].image);
    gtk_container_add(GTK_CONTAINER (hbox_1), event_box1);
    gtk_container_add(GTK_CONTAINER (hbox_1), event_box2);
    gtk_container_add(GTK_CONTAINER (hbox_1), event_box3);
    gtk_container_add(GTK_CONTAINER (event_box1), card[0].image);
    gtk_container_add(GTK_CONTAINER (event_box2), card[1].image);
    gtk_container_add(GTK_CONTAINER (event_box3), card[2].image);
    gtk_container_add(GTK_CONTAINER (hbox_3), card[3].image);
    gtk_container_add(GTK_CONTAINER (hbox_3), card[4].image);
    gtk_container_add(GTK_CONTAINER (hbox_3), card[5].image);
    gtk_container_add(GTK_CONTAINER (hbox_table), card[6].image);
    gtk_container_add(GTK_CONTAINER (hbox_table), card[7].image);   

    gtk_widget_show_all (window);

    gtk_main();

}

void card1_clicked (GtkWidget *window, struct my_image *card)
{
    printf("%s\n", card[0].path);
    card[6].image = card[0].image;
    /*gtk_image_set_from_file(GTK_IMAGE(card[6].image), card[0].path);*/
}

the images initially are displayed correclty but when trigger card1_clciked this line card[6].image = card[0].image; produces a Segmentation Fault. I'm not sure if I'm loading the image correctly and how to load another image using the same widget; I've also tried to use the function /*gtk_image_set_from_file(GTK_IMAGE(card[6].image), card[0].path);* with the same effect.


Solution

  • Your callback function for button_press_event signal is not defined properly.

    The manual tells us how it shall look like:

    // The “button-press-event” signal
    
    gboolean
    user_function (GtkWidget *widget,
                   GdkEvent  *event,
                   gpointer   user_data)
    

    In your function you are missing one parameter:

    void card1_clicked (GtkWidget *window, struct my_image *card)
    

    This means you are using the event pointer to read your card array which causes some illegal read access.

    Besides that you do not provide the required boolean return value.