Drawing lines with GTK+ and Cairo without removing what is already drawn

╄→гoц情女王★ 提交于 2020-05-31 06:54:40

问题


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. I can't figure out a way to draw to the window with a proper function call.
  2. It removes what is already drawn.

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

  1. Draw lines to a GTK window with a function call, given X and Y for both starting and end point;
  2. Do not remove what is previously drawn;
  3. All initializations of variables and the window should be outside the main function.

So basically something similar to this:

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

Also please include the gcc build command used.

Thanks in advance!


回答1:


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

Build the program as usual:

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


来源:https://stackoverflow.com/questions/34136892/drawing-lines-with-gtk-and-cairo-without-removing-what-is-already-drawn

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!