如何捕获GTK窗口并将其写入PNG文件?

时间:2017-06-08 06:21:25

标签: c gtk gtk3

这是我尝试的内容:

#include <gtk/gtk.h>

static GtkWidget *window, *drawing_area;

static gboolean drawCallback(GtkWidget *widget, cairo_t *cr, gpointer arg) {

    cairo_set_source_rgb(cr, 1.0, 0, 0);
    cairo_arc(cr, 200.0, 150.0, 50.0, 0, 2*G_PI);
    cairo_fill(cr);
}

static gboolean savePNG(gpointer arg) {

    cairo_surface_t *surface = cairo_image_surface_create(
        CAIRO_FORMAT_RGB24, 400, 300
    );
    cairo_t *cr = cairo_create(surface);

    gdk_cairo_set_source_window(
        cr,
        gtk_widget_get_window(GTK_WIDGET(window)),
        0, 0
    );

    printf("cairo_status(cr): %s\ncairo_surface_status(surface): %s\n",
        cairo_status_to_string(cairo_status(cr)),
        cairo_status_to_string(cairo_surface_status(surface)));

    cairo_surface_write_to_png(surface, "test.png");
}

static void app_activate(GtkApplication *app, gpointer user_data) {

    window = gtk_application_window_new(app);
    gtk_window_set_title(GTK_WINDOW(window), "Sandbox");
    gtk_widget_set_size_request(GTK_WIDGET(window), 400, 300);
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);

    drawing_area = gtk_drawing_area_new();
    gtk_container_add(GTK_CONTAINER(window), drawing_area);
    g_signal_connect(G_OBJECT(drawing_area), "draw", G_CALLBACK(drawCallback), NULL);

    gtk_widget_show_all(window);
    gtk_window_move(GTK_WINDOW(window), 10, 10);
}

int main(int argc, char **argv) {

    GtkApplication *app;
    int status;

    app = gtk_application_new("the.application.id", G_APPLICATION_FLAGS_NONE);
    g_signal_connect(app, "activate", G_CALLBACK(app_activate), NULL);

    g_timeout_add(1000, savePNG, NULL);

    status = g_application_run(G_APPLICATION(app), argc, argv);

    g_object_unref(app);
    return status;
}

窗口显示一个红色圆圈,但创建的 test.png 文件包含全黑图像。

这是输出:

cairo_status(cr): no error has occurred
cairo_surface_status(surface): no error has occurred

This answer提出了我使用过的模式。

1 个答案:

答案 0 :(得分:1)

在保存之前,你忘了在表面上画任何东西。

static gboolean savePNG(gpointer arg)
{
  cairo_surface_t *surface = cairo_image_surface_create(CAIRO_FORMAT_RGB24, 300, 200);  // <<= Reduced size to get only a part of the window.
  cairo_t *cr = cairo_create(surface);

  cairo_translate(cr, -50.0, -50.0);  // <<= Move the part we want to copy from source into position....

  gdk_cairo_set_source_window(
      cr,
      gtk_widget_get_window(GTK_WIDGET(window)),
      0, 0
  );
  cairo_paint(cr);  // <<= DO IT! ;)
  cairo_surface_write_to_png(surface, "test.png");
}

编辑:

我更新了代码,只将窗口的一部分复制到文件中。 您需要将源移动到所需窗口部分的新起点。当然,你的表面也需要更小。