C语言 如何在 GTK+3 的 gtk 窗口中创建 cairo 对象



我试图使用开罗画一些弧线,但 gcc 警告我gdk_cairo_create() is deprecated. Use gdk_window_begin_draw_frame() and gdk_drawing_context_get_cairo_context() instead.

为了解决这个问题,我做了一些研究,发现对于gdk_window_begin_draw_frame((,我需要"GdkWindow"。我一直在为我的窗口使用 GtkWidget,所以我需要将"GtkWidget"转换为"GdkWindow",但 gtk_widget_get_window(( 返回 NULL 并导致段错误。

#include <gtk/gtk.h>
#include <cairo.h>
void main(int argc , char **argv){
gtk_init(&argc , &argv);
GtkWidget *win;
GdkWindow *gdkwin;
GdkDrawingContext *dc;
cairo_region_t *region;
cairo_t *cr;

win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
region = cairo_region_create();
gdkwin = gtk_widget_get_window(GTK_WIDGET(win));
//Here gdkwin should contain a GdkWindow but it's NULL.
gc = gdk_window_begin_draw_frame(gdkwin , (const cairo_region_t*)&region);
...
...

下面是运行时错误:

(a.out:6852): Gdk-CRITICAL **: 23:53:06.042: gdk_window_begin_draw_frame: assertion 'GDK_IS_WINDOW (window)' failed
(a.out:6852): Gdk-CRITICAL **: 23:53:06.042: gdk_drawing_context_get_cairo_context: assertion 'GDK_IS_DRAWING_CONTEXT (context)' failed
Segmentation fault

我想获取一个开罗对象并将其用于 cairo_arc((。

谢谢,最好的问候。

以下是让Cairo在GTK 3下工作的完整源代码。它应该是可按原样编译的。

正如其他人已经指出的那样,您必须使用绘制信号才能使事情正常工作。

#include <gtk/gtk.h>
#include <cairo.h>
// ------------------------------------------------------------
gboolean on_draw (GtkWidget *widget,
GdkEventExpose *event,
gpointer data) 
{
// "convert" the G*t*kWidget to G*d*kWindow (no, it's not a GtkWindow!)
GdkWindow* window = gtk_widget_get_window(widget);  
cairo_region_t * cairoRegion = cairo_region_create();
GdkDrawingContext * drawingContext;
drawingContext = gdk_window_begin_draw_frame (window,cairoRegion);
{ 
// say: "I want to start drawing"
cairo_t * cr = gdk_drawing_context_get_cairo_context (drawingContext);
{ // do your drawing
cairo_move_to(cr, 30, 30);
cairo_set_font_size(cr,15);
cairo_show_text(cr, "hello world");
}
// say: "I'm finished drawing
gdk_window_end_draw_frame(window,drawingContext);
}
// cleanup
cairo_region_destroy(cairoRegion);
return FALSE;
}
// ------------------------------------------------------------
int main (int argc, char * argv[]) {
gtk_init(&argc, &argv);
GtkWindow * window; 
{ // window setup
window = (GtkWindow*)gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_default_size (window, 200, 200);
gtk_window_set_position     (window, GTK_WIN_POS_CENTER);
gtk_window_set_title        (window, "Drawing");
g_signal_connect(window, "destroy", gtk_main_quit, NULL);
}  
// create the are we can draw in
GtkDrawingArea* drawingArea;
{
drawingArea = (GtkDrawingArea*) gtk_drawing_area_new();
gtk_container_add(GTK_CONTAINER(window), (GtkWidget*)drawingArea);
g_signal_connect((GtkWidget*)drawingArea, "draw", G_CALLBACK(on_draw), NULL);    
}  

gtk_widget_show_all ((GtkWidget*)window);
gtk_main();
return 0;
}

// ------------------------------------------------------------

在 GTK+ 3 中,您应该响应draw信号进行绘图。在 main 中执行此操作是没有意义的(小部件刚刚创建,但在运行主事件循环时进一步初始化它们(。

请阅读:https://developer.gnome.org/gtk3/stable/chap-drawing-model.html

The Dark Trick的程序已经完成。 他使用的功能如下,

GdkWindow* window = gtk_widget_get_window (widget);
cairo_region_t *cairoRegion = cairo_region_create();
GdkDrawingContext *drawingContext;
drawingContext = gdk_window_begin_draw_frame (window, cairoRegion);
cairo_t *cr = gdk_drawing_context_get_cairo_context (drawingContext);

但是我正在使用如下功能,

GdkWindow *window = gtk_widget_get_window(widget);
cairo_rectangle_int_t cairoRectangle = {0, 0, 200, 200};
cairo_region_t *cairoRegion = cairo_region_create_rectangle (&cairoRectangle);
GdkDrawingContext *drawingContext;
drawingContext = gdk_window_begin_draw_frame (window,cairoRegion);
cairo_t *cr = gdk_drawing_context_get_cairo_context (drawingContext);

这奏效了,但我无法理解差异,因为我是一名老泌尿科医生。

我不是肯定的,但我认为您正在尝试在 GdkWindow 准备就绪之前获取它。我认为您需要连接到窗口的"实现"信号,并且只有在发出该信号时,您才应该尝试访问底层 GdkWindow。

#include <gtk/gtk.h>
#include <cairo.h>

void OnWindowRealize(GtkWidget *pWidget, gpointer data)
{
GdkWindow *pUnderlyingWindow = gtk_widget_get_window(pWidget);
cairo_region_t *region = cairo_region_create();
GdkDrawingContext *gc = gdk_window_begin_draw_frame(pUnderlyingWindow, (const cairo_region_t*)&region);
//etc...
}

void main(int argc , char **argv)
{
gtk_init(&argc , &argv);
GtkWidget *win = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(G_OBJECT(win), "realize", OnWindowRealize, NULL);
//etc...
}

最新更新