使用GTK +和Cairo绘制线条而不会删除已绘制的内容 [英] Drawing lines with GTK+ and Cairo without removing what is already drawn

查看:119
本文介绍了使用GTK +和Cairo绘制线条而不会删除已绘制的内容的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在Linux系统(确切地说是Raspberry Pi)上用C编写程序,该程序应该使用Cairo绘制到GTK窗口。我一直在以下位置关注本教程: http://zetcode.com/gfx/cairo/ 。但这是在某些点上模糊其解释的方法。

Currently I am writing a program in C, on a linux system (Raspberry Pi to be exact) which should draw to a GTK window using Cairo. I've been following the tutorial at: http://zetcode.com/gfx/cairo/ . But it is way to vague with it's explanations at certain points.

它并不能解释我真正需要的两点:

It does not explain two points that I really need:


  1. 我想不出一种通过适当的函数调用绘制到窗口的方法。

  2. 它会删除已经绘制的内容。

我需要一段代码,以非常面向对象的方式做一些简单的事情:

I need a piece of code that does some simple things, in a very Object-Oriented manner:


  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);
    }
}

如果可以解释方法的作用(在

If it could be explained what a method does (in proper English please, not a reference to the documentation), that'd be absolutely great.

还请包括所用的gcc build命令。

Also please include the gcc build command used.

谢谢!

推荐答案

andlabs的回答很好。另外,这是一个简短的示例(尽管并不十分优雅)。最后一行 NUM 行将记住-窗口的创建/调整大小/激活/停用将触发内容的绘制。单击下一步按钮将在输出中添加新行。还要检查命令行输出中
绘制数组值的更新。

The answers from andlabs are fine. Here is in addition a short (although not entirely elegant) example. It will "kind of remember" the last NUM lines - creation/resize/activation/deactivation of the window will trigger a "draw" of the content. A Next button click will add a new line to the output. Check also the command-line output for an update of the array values that are drawn.

#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`

这篇关于使用GTK +和Cairo绘制线条而不会删除已绘制的内容的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆