GtkDrawingArea - 如何让它成为可绘制的?

时间:2012-02-22 12:51:49

标签: gtk cairo

我有点想到这里。

我正在尝试使用cairo在我的GTK表单上绘制一些简单的图形。

#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   (可绘制)'失败

然后是段错误。

我一直在关注tutorial here

所以我按如下方式更改了代码,使得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); 

告诉程序'当暴露事件发生在darea时,然后调用on_expose_event'。 null是您可以传入指向要使用的函数的附加信息的结构的指针的位置。

    static gboolean
    on_expose_event(GtkWidget *widget,
        GdkEventExpose *event,
        gpointer data)
    {

表示on_expose_event传递指向事件发生的窗口小部件的指针,在这种情况下,因为它是一个公开事件,一个指向包含有关公开事件的信息的结构的指针,以及一个指向任何其他信息的结构的指针你可能想补充一下。

2 个答案:

答案 0 :(得分:9)

使用Cairo 仅在上绘制窗口小部件可以在公开事件中使用。这是因为开罗不像矢量绘图程序,其中线条和形状是被记住并可被操纵的对象;开罗只是将形状描绘到绘图区域并忘记它们。

因此,当您最小化并恢复窗口,或在其上方移动另一个窗口时,形状将消失。生成一个公开事件,让您知道形状已消失,并且需要重新绘制窗口小部件。所以你在曝光事件处理程序中使用Cairo进行重绘。

答案 1 :(得分:2)

第一个代码中的警告和随之而来的崩溃是因为darea->window NULLGdkWindow darea->windowgdk_cairo_create)尚未创建当你拨打GdkWindow时指向程序。绘图区域小部件实现后,将创建绘图区域gtk_widget_realize(darea);。尝试在致电gdk_cairo_create之前添加window。此外,我可以建议使用访问者函数gtk_widget_get_window,而不是直接访问expose-event 之所以没有断言&amp;在GdkWindow回调中添加相同代码时崩溃是因为在执行程序时已经创建了与绘图区域相关联的expose-event

编辑:
上面提供的原因只是 来解释为什么代码没有崩溃gdk_cairo_create回调&amp;为什么调用{{1}}在程序运行时没有断言。将上述响应视为与崩溃相关的解释。有关绘图机制的详细信息,请参阅ptomato's response

希望这有帮助!