Я немного схожу с ума здесь.
Я пытаюсь нарисовать простую графику в моей форме GTK, используя cairo.
#include <stdio.h>
#include <gtk/gtk.h>
#include <cairo.h>
GtkWidget* window;
GtkWidget* darea;
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 390, 240);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
cairo_t *cr;
cr = gdk_cairo_create(darea->window);
cairo_rectangle(cr, 0, 0, 100, 100);
cairo_fill(cr);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Это компилируется, но дает мне
Gdk-CRITICAL **: IA__gdk_cairo_create: утверждение `GDK_IS_DRAWABLE
(отрисовка) 'не удалось
с последующим сегфоутом.
Я смотрел учебник здесь
Поэтому я изменил свой код следующим образом, чтобы вызовы cairo происходили внутри события expose.
#include <stdio.h>
#include <gtk/gtk.h>
#include <cairo.h>
GtkWidget* window;
GtkWidget* darea;
static gboolean
on_expose_event(GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
cairo_t *cr;
cr = gdk_cairo_create(darea->window);
cairo_rectangle(cr, 0, 0, 100, 100);
cairo_fill(cr);
}
int main(int argc, char **argv)
{
gtk_init(&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size(GTK_WINDOW(window), 390, 240);
darea = gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), darea);
g_signal_connect(darea, "expose-event",
G_CALLBACK(on_expose_event), NULL);
gtk_widget_show_all(window);
gtk_main();
return 0;
}
Почему это исправляет?
Мое понимание: разоблачение:
Символ
g_signal_connect(darea, "expose-event", G_GCALLBACK(on_expose_event), NULL);
сообщает программе: «когда событие expose происходит с darea, тогда вызовите on_expose_event». Нулевое значение - это место, где вы можете передать указатель на структуру дополнительной информации, которую должна использовать функция.
и
static gboolean
on_expose_event(GtkWidget *widget,
GdkEventExpose *event,
gpointer data)
{
означает, что on_expose_event передается указатель на виджет, с которым произошло событие, и в этом случае, потому что это событие expose, указатель на структуру, содержащую информацию о событии expose, и указатель на структуру на любую другую информацию Вы можете добавить.