c - 使用GTK+和开罗绘制线,而无需删除已经绘制的内容

标签 c linux gtk gtk3 cairo

目前,我在Linux系统(准确地说是Raspberry Pi)上编写了一个程序,该程序应使用开罗绘制到GTK窗口。我一直在关注该教程:http://zetcode.com/gfx/cairo/ 。但这是在某些方面模糊的解释。

它没有解释我真正需要的两点:

  1. 我无法找到一种使用正确功能调用到窗口的方法。
  2. 它删除了已经绘制的内容。

我需要以非常面向对象的方式进行一些简单的代码:

  1. 用函数调用将行绘制到GTK窗口,给定x和y,用于起点和终点;
  2. 请勿删除以前绘制的内容;
  3. 变量和窗口的所有初始化都应在主要功能之外。

基本上与此类似:

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

void drawLine(int xStart, int yStart, int yEnd, int xEnd) {
    //Drawing code here.
}

void initializeCairo() {
    //Insert cairo initialization.
}

void initializeGTK() {
    //Insert GTK initialization.
}

/*If needed a general initializer for both cairo and GTK*/
void initialize() {
    //Insert general initialization.
}

int main (int argc, char *archv[]) {
    intializeGTK();
    initializeCairo();
    if(doSomething) {
        drawLine(10, 10, 20, 20);
    }
}

如果可以解释一种方法的作用(请用适当的英语用,而不是对文档的引用),那将是绝对不错的。

也请包括使用的GCC构建命令。

提前致谢!

最佳答案

andlabs 的答案很好。另外还有一个简短的(尽管不完全优雅)示例。它会“记住”最后 NUM 行 - 窗口的创建/调整大小/激活/停用将触发内容的“绘制”。单击“下一步”按钮将在输出中添加新行。另请检查命令行输出以获取更新 绘制的数组值。

#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include <cairo.h>
#include <math.h>
#include <stdio.h>
#include <string.h>

#define NUM 3

typedef struct {
    GtkApplication *app;
    GtkWidget *window;
    GtkWidget *button;
    GtkWidget *da;
    cairo_t* cr;
    gboolean redraw;
    gint xsize;
    gint ysize;
} appWidgets;

gboolean drawEvent (GSimpleAction *action, GVariant *parameter, gpointer data);
void nextCallback (GtkWidget *widget, gpointer data);

void nextCallback (GtkWidget *widget, gpointer data)
{
    appWidgets *w = (appWidgets*) data;

    static gint cnt = 0;
    static gdouble x[NUM], y[NUM], u[NUM], v[NUM];

    // determine the next coordinates for a line
    if (w->redraw == FALSE) {
        x[cnt] = g_random_double();
        y[cnt] = g_random_double();
        u[cnt] = g_random_double();
        v[cnt] = g_random_double();
    }
    w->cr = gdk_cairo_create (gtk_widget_get_window (w->da));
    // map (0,0)...(xsize,ysize) to (0,0)...(1,1)
    cairo_translate (w->cr, 0, 0);
    cairo_scale (w->cr, w->xsize, w->ysize);
    // set linewidth
    cairo_set_line_width (w->cr, 0.005);
    // draw the lines
    for (int k = 0; k < NUM; k++) {
        cairo_move_to (w->cr, x[k], y[k]);
        cairo_line_to (w->cr, u[k], v[k]);
        cairo_stroke (w->cr);
        g_print("k=%d:(%1.2lf,%1.2lf).(%1.2lf,%1.2lf) ", 
            k, x[k], y[k], u[k], v[k]);
    }
    g_print("\n");
    cairo_destroy (w->cr);
    if (w->redraw == FALSE) {
        cnt++;
        if (cnt == NUM)
            cnt = 0;
    }
}

gboolean drawEvent (GSimpleAction *action, GVariant *parameter, gpointer data)
{
    appWidgets *w = (appWidgets*) data;

    w->xsize = gtk_widget_get_allocated_width (w->da);
    w->ysize = gtk_widget_get_allocated_height (w->da);
    w->redraw = TRUE;
    nextCallback (NULL, w);
    w->redraw = FALSE;
    return TRUE;
}

void activate (GtkApplication *app, gpointer data)
{
    GtkWidget *box;
    appWidgets *w = (appWidgets*) data;

    w->window = gtk_application_window_new (w->app);
    gtk_window_set_application (GTK_WINDOW (w->window), GTK_APPLICATION (w->app));
    box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
    gtk_container_add (GTK_CONTAINER (w->window), box);
    w->da = gtk_drawing_area_new();
    gtk_widget_set_size_request (w->da, 400, 400);
    gtk_box_pack_start (GTK_BOX (box), w->da, TRUE, TRUE, 0);
    g_signal_connect (w->da, "draw", G_CALLBACK (drawEvent), (gpointer) w);
    w->button = gtk_button_new_with_label ("Next");
    g_signal_connect (G_OBJECT (w->button), "clicked", G_CALLBACK (nextCallback), 
                    (gpointer) w);
    gtk_box_pack_start (GTK_BOX (box), w->button, FALSE, TRUE, 0);
    gtk_widget_show_all (GTK_WIDGET (w->window));
    w->redraw = FALSE;
}

int main (int argc, char *argv[])
{
    gint status;
    appWidgets *w = g_malloc (sizeof (appWidgets));

    w->app = gtk_application_new ("org.gtk.example", G_APPLICATION_FLAGS_NONE);
    g_signal_connect (w->app, "activate", G_CALLBACK (activate), (gpointer) w);
    status = g_application_run (G_APPLICATION (w->app), argc, argv);

    g_object_unref (w->app);
    g_free (w);
    w = NULL;
    return status;
}

照常构建程序:

gcc example.c -o example `pkg-config --cflags --libs gtk+-3.0`

关于c - 使用GTK+和开罗绘制线,而无需删除已经绘制的内容,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34136892/

相关文章:

c - 协助查找数组的高点和低点并将数组设置为零

c - 一致的数组参数是 VLA 吗?

c - 为什么我的代码中的第二个 strcpy() 导致停止工作?

C 结构体、字符串和段错误

linux - 杀死一个 tid 不会返回错误

linux - 如何统计Linux日志文件中 'Mozilla'用户代理的数量

java - 创建 war 文件

python - 不使用 gtk 显示图像

Python GTK - 将鼠标点击传递到下面的窗口

linux - Linux应用本地化