Hi, i am stuck in implementing a simple app with GTK3.
I want to display 9 GtkDrawingArea on a grid and rearrange them when the window is resized.
I connect the main window’s “size-allocate” event to a callback function that removes all grid widgets and set them to the desired location. This function works as expected.
Now i want to get click event on the GtkDrawingArea. I do this (just for test on one GtkDrawingArea)
gtk_widget_add_events (app.img[0], GDK_BUTTON_PRESS_MASK);
g_signal_connect (app.img[0], "button-press-event", G_CALLBACK (button_press_event), NULL);
But seems that the GtkDrawingArea do not respond to a “button-press-event”.
I found that this is related to the code used in the “size-allocate” event callback function (if i do not connect the size-allocate signal, the GtkDrawingArea will respond to a “button-press-event”).
I don’t know how to make it work as expected.
Here is the full code
#include <stdlib.h>
#include <gtk/gtk.h>
struct app_wdg {
GtkWidget *grd;
GtkWidget *win;
GtkWidget *sll;
GtkWidget *img[9];
};
void add_images(struct app_wdg *app)
{
gint i=0, x=0, y=0;
gint width=0;
gint height=0;
width = gtk_widget_get_allocated_width(app->sll);
for(i = 0; i < 9; i = i + 1)
{
gtk_grid_attach(GTK_GRID(app->grd), app->img[i], x, y, 1, 1);
x = x + 1;
if ((x+1)*100 + 30 >= width)
{
x = 0;
y = y + 1;
}
}
}
static gboolean button_press_event (GtkWidget* self, GdkEventButton *event)
{
g_print("Clicked!\n");
return TRUE;
}
static void size_allocate (GtkWidget* self, GtkAllocation* allocation, gpointer user_data)
{
struct app_wdg *app = (struct app_wdg *)(user_data);
GList *children = gtk_container_get_children(GTK_CONTAINER(app->grd));
for (const GList *iter = children; iter != NULL; iter = g_list_next(iter))
{
g_object_ref(iter->data);
gtk_container_remove(GTK_CONTAINER(app->grd), iter->data);
}
add_images(app);
}
static gboolean on_draw (GtkWidget *self, cairo_t *cr, gpointer data)
{
GdkPixbuf *pix;
GError *err = NULL;
pix = gdk_pixbuf_new_from_file(data, NULL);
pix = gdk_pixbuf_scale_simple(pix, 100, 100, GDK_INTERP_NEAREST);
gdk_cairo_set_source_pixbuf(cr, pix, 0, 0);
cairo_paint(cr);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_set_line_width(cr, 3);
cairo_rectangle(cr, 0, 0, 100, 100);
cairo_stroke(cr);
return TRUE;
}
int main (int argc, char *argv[])
{
struct app_wdg app;
/* Initialize GTK+ */
gtk_init (&argc, &argv);
/* Create widgets */
app.win = gtk_window_new (GTK_WINDOW_TOPLEVEL);
app.grd = gtk_grid_new ();
app.sll = gtk_scrolled_window_new (NULL, NULL);
app.img[0] = gtk_drawing_area_new ();
app.img[1] = gtk_drawing_area_new ();
app.img[2] = gtk_drawing_area_new ();
app.img[3] = gtk_drawing_area_new ();
app.img[4] = gtk_drawing_area_new ();
app.img[5] = gtk_drawing_area_new ();
app.img[6] = gtk_drawing_area_new ();
app.img[7] = gtk_drawing_area_new ();
app.img[8] = gtk_drawing_area_new ();
gtk_widget_set_size_request (app.img[0], 100, 100);
gtk_widget_set_size_request (app.img[1], 100, 100);
gtk_widget_set_size_request (app.img[2], 100, 100);
gtk_widget_set_size_request (app.img[3], 100, 100);
gtk_widget_set_size_request (app.img[4], 100, 100);
gtk_widget_set_size_request (app.img[5], 100, 100);
gtk_widget_set_size_request (app.img[6], 100, 100);
gtk_widget_set_size_request (app.img[7], 100, 100);
gtk_widget_set_size_request (app.img[8], 100, 100);
/* Set widgets */
/* win */
gtk_container_set_border_width (GTK_CONTAINER (app.win), 8);
gtk_window_set_title (GTK_WINDOW (app.win), "img_tab");
gtk_window_set_position (GTK_WINDOW (app.win), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request (app.win, 300, 300);
/* grid */
gtk_grid_set_column_spacing(GTK_GRID(app.grd),6);
gtk_grid_set_row_spacing(GTK_GRID(app.grd),6);
/* Add widgets to containers */
gtk_container_add(GTK_CONTAINER(app.win), app.sll);
gtk_container_add(GTK_CONTAINER(app.sll), app.grd);
add_images(&app);
/* Add callbacks */
g_signal_connect (app.win, "size-allocate", G_CALLBACK (size_allocate), &app);
g_signal_connect (app.win, "destroy", gtk_main_quit, NULL);
g_signal_connect (app.img[0], "draw", G_CALLBACK (on_draw), "./bin/Debug/0.png");
g_signal_connect (app.img[1], "draw", G_CALLBACK (on_draw), "./bin/Debug/1.png");
g_signal_connect (app.img[2], "draw", G_CALLBACK (on_draw), "./bin/Debug/2.png");
g_signal_connect (app.img[3], "draw", G_CALLBACK (on_draw), "./bin/Debug/3.png");
g_signal_connect (app.img[4], "draw", G_CALLBACK (on_draw), "./bin/Debug/4.png");
g_signal_connect (app.img[5], "draw", G_CALLBACK (on_draw), "./bin/Debug/5.png");
g_signal_connect (app.img[6], "draw", G_CALLBACK (on_draw), "./bin/Debug/6.png");
g_signal_connect (app.img[7], "draw", G_CALLBACK (on_draw), "./bin/Debug/7.png");
g_signal_connect (app.img[8], "draw", G_CALLBACK (on_draw), "./bin/Debug/8.png");
gtk_widget_add_events (app.img[0], GDK_BUTTON_PRESS_MASK);
g_signal_connect (app.img[0], "button-press-event", G_CALLBACK (button_press_event), NULL);
/* Enter the main loop */
gtk_widget_show_all (app.win);
gtk_main ();
return 0;
}