使用GTK +和Cairo绘制线条而不删除已绘制的内容

时间:2015-12-07 15:14:12

标签: c linux gtk gtk3 cairo

目前我正在使用Cairo在Linux系统上编写一个程序(确切地说是Raspberry Pi),它应该使用Cairo绘制到GTK窗口。我一直在关注教程:http://zetcode.com/gfx/cairo/。但是它在某些方面对它的解释含糊不清。

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

  1. 我无法通过正确的函数调用找到一种绘制窗口的方法。
  2. 删除已经绘制的内容。
  3. 我需要一段以面向对象的方式执行一些简单操作的代码:

    1. 使用函数调用在GTK窗口中绘制线条,给出起点和终点的X和Y;
    2. 不要删除之前绘制的内容;
    3. 变量和窗口的所有初始化都应该在主函数之外。
    4. 所以基本上类似于此:

      #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 build命令。

      提前致谢!

1 个答案:

答案 0 :(得分:2)

来自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`