当前位置: 首页 > 知识库问答 >
问题:

使用开罗绘制到 GTK/GDK 绘图区域

彭礼骞
2023-03-14

在GDK/GTK中检索开罗上下文的机制已损坏和/或在文档中未正确描述。我正在尝试从按钮按回调中绘制Gtk绘制区域,但没有成功。文档建议做

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

然后用开罗的语境画画,然后在

gdk_window_end_draw_frame( window, drawingContext );
cairo_region_destroy( cairoRegion );

所有这些似乎都适用于GTK 3.22.30(和cairo 1.15.12),但不适用于GTK3.24.30(和cair 1.16.0)。显然有些事情已经改变了。知道吗?下面是一个完整的例子:

// gcc -Wextra -o hauki hauki.c `pkg-config --cflags --libs gtk+-3.0`
#include <gtk/gtk.h>

gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
{   
   // This works
   cairo_set_source_rgb(cr, 1, 1, 1);
   cairo_paint(cr);
   return FALSE;
}

gboolean button_cb( GtkWidget *widget, GdkEventButton *event, gpointer object )
{
    GdkWindow *window = gtk_widget_get_window( GTK_WIDGET(widget) );

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

    cairo_set_source_rgb(cr, 1, 0, 0);
    cairo_move_to(cr, 0, 0);
    cairo_line_to(cr, 300, 300);
    cairo_stroke(cr);
    
    gdk_window_end_draw_frame( window, drawingContext );
    cairo_region_destroy( cairoRegion );
}


int main (int argc, char *argv[])
{
   gtk_init( &argc, &argv );

   GtkWidget *window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
   g_signal_connect( window, "destroy", G_CALLBACK (gtk_main_quit), NULL );

   GtkWidget *da = gtk_drawing_area_new();
   gtk_widget_add_events( da, GDK_BUTTON_PRESS_MASK );
   gtk_widget_set_size_request( da, 300, 300 );
   g_signal_connect( da, "draw", G_CALLBACK(draw_cb), NULL );
   g_signal_connect( da, "button_press_event", G_CALLBACK(button_cb), NULL );
   
   gtk_container_add( GTK_CONTAINER (window), da );
   gtk_widget_show( da );
   gtk_widget_show( window );

   gtk_main();

   return 0;
}

共有1个答案

宋唯
2023-03-14

< code > gdk _ window _ begin _ draw _ frame()是一个低级调用,通常只在您尝试使用GDK/Cairo绘制东西而不涉及GTK时才需要它。既然你明显在用GTK,你就不应该用它。

在GTK用Cairo绘图的方法是使用< code>GtkDrawingArea(或者如果您想实现非常自定义的行为:子类化< code>GtkWidget并实现您自己的< code>draw() vfunc)。正如您已经看到的,它有一个< code>draw信号,您可以将一个回调连接到该信号:每次小部件需要重画自己时,都会调用该回调。

换句话说,您的绘制回调应该根据特定状态更改其绘制方式:

#include <gtk/gtk.h>

gboolean button_clicked = FALSE;

gboolean draw_cb(GtkWidget *widget, cairo_t *cr, gpointer data)
{
    if (button_clicked) {
        cairo_set_source_rgb(cr, 1, 0, 0);
        cairo_move_to(cr, 0, 0);
        cairo_line_to(cr, 300, 300);
        cairo_stroke(cr);
    }

    return FALSE;
}

gboolean button_cb( GtkWidget *widget, GdkEventButton *event, gpointer object )
{
    button_clicked = TRUE;
    // Explicitly notify the drawing area it should redraw itself
    gtk_widget_queue_draw (widget);
}

int main (int argc, char *argv[])
{
   gtk_init( &argc, &argv );

   GtkWidget *window = gtk_window_new( GTK_WINDOW_TOPLEVEL );
   g_signal_connect( window, "destroy", G_CALLBACK (gtk_main_quit), NULL );

   GtkWidget *da = gtk_drawing_area_new();
   gtk_widget_add_events( da, GDK_BUTTON_PRESS_MASK );
   gtk_widget_set_size_request( da, 300, 300 );
   g_signal_connect( da, "draw", G_CALLBACK(draw_cb), NULL );
   g_signal_connect( da, "button_press_event", G_CALLBACK(button_cb), NULL );
   
   gtk_container_add( GTK_CONTAINER (window), da );
   gtk_widget_show( da );
   gtk_widget_show( window );

   gtk_main();

   return 0;
}
 类似资料:
  • 我想只显示绘图区域内的开罗绘图,但由于某种原因,绘图周围总是有一个彩色矩形形状的背景。我如何摆脱这种情况?我特别不想将其设置为仅透明(因为我可能不支持透明),而只显示绘图本身。 我的例子是在 Rust 中使用 gtk-rs,但其他语言中的任何提示也很棒! 我希望这只显示圆,并查看并保持浏览器在圆周围可单击。我如何才能做到这一点?

  • 所以,我想用PyCairo绘制一个图像。效率非常重要,但我使用PyGtk的gtk.gdk.Pixbuf加载图像。我的问题是,通过gtk.gdk检索开罗上下文来呈现Pixbuf是否有性能差异。CairoContext与将Pixbuf转换为cairo的对比。ImageSurface对象,如果是,差异有多大?这是在一个单独的绘图线程中运行的,该线程每秒更新30次左右(但仅当图像需要更新时)。请注意,转换

  • 问题内容: 我正在尝试使用Java的Graphics2D在屏幕上绘制图像。这是我正在使用的代码。我想看到图像在屏幕上稳定移动。目前,我可以看到图像,但是除非调整窗口大小,否则图像不会移动,在这种情况下,图像确实会移动。我已经勾勒出以下课程。 传递给Tester的Component对象是以下类: 我确保此类仅添加了一个精灵。Sprite类大致如下: 但是,我在屏幕上仅看到固定的Bowser图像。除非

  • 我正试着用Jupyter笔记本画热图。我的表由10个列和许多行组成。第一行是列名。我正在使用plotly lib。 dfs是数据帧。 而不是图形,我得到了很多这样的线条: '\n跟踪=判(\n x=x,y=y,z=z,\n类型="散射3d",\n模式=\'标记\',\n标记=判(大小=5,颜色=\'黑色\',线=判(宽度=0)))\n数据=[跟踪]\n\n\n etc 有什么问题?

  • 我正试图用PDFbox绘制饼图,但各片之间有白线,有人能帮我吗?是否有此选项? 附上我正在使用的绘制圆弧的代码: 结果的附加图像: 谢啦

  • 操作步骤: 第一种:添加圆形区域 ①进入编辑界面,选择区域图层后,点击右上角"添加圆形区域"。 ②在地图上"点击并拖拽绘制圆形" ,释放鼠标完成绘制。 ③点击"完成"按钮,圆形区域添加完成。 第二种:添加区域 ①进入编辑界面,选择区域图层后,点击右上角"添加区域"。 ②在地图上"点击开始绘制区域" ,双击鼠标完成绘制。 注意 ●添加区域不可少于3个节点。 ③点击"完成"按钮,区域绘制完成。 操作动