2015-12-07 5 views
0

Actuellement j'écris un programme en C, sur un système Linux (Raspberry Pi pour être exact) qui devrait dessiner dans une fenêtre GTK en utilisant Cairo. J'ai suivi le tutoriel au: http://zetcode.com/gfx/cairo/. Mais il est trop vague avec ses explications sur certains points.Tracer des lignes avec GTK + et Cairo sans enlever ce qui est déjà dessiné

Il n'explique pas deux points que j'ai vraiment besoin:

  1. Je ne peux pas trouver un moyen de tirer à la fenêtre avec un appel de fonction appropriée.
  2. Il supprime ce qui est déjà dessiné.

je besoin d'un morceau de code qui fait des choses simples, d'une manière très orientée objet:

  1. Dessiner des lignes à une fenêtre GTK avec un appel de fonction, étant donné X et Y pour les départ et point final;
  2. Ne retirez pas ce qui a été précédemment dessiné;
  3. Toutes les initialisations de variables et la fenêtre doivent être en dehors de la fonction principale.

Donc, fondamentalement, quelque chose de similaire à ceci:

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

Si l'on pouvait expliquer ce qu'est une méthode fait (en anglais bon s'il vous plaît, pas une référence à la documentation), ce serait tout à fait génial.

Veuillez également inclure la commande gcc build utilisée.

Merci d'avance!

+4

Le modèle GTK + dessin est « le GtkWidget vous informera quand il a besoin d'être redessinée par l'émission d'un' draw' signal; avant que ce signal est émis, il va effacer le widget pour vous donner une ardoise vierge à dessiner ". Si vous voulez conserver le contenu de la zone de dessin, vous devrez le faire vous-même (peut-être en sauvegardant les paramètres du dessin, dans votre cas une liste de lignes). Vous ne pouvez pas forcer un redraw immédiatement, mais vous pouvez indiquer à GTK + que vous voulez redessiner en utilisant la méthode 'gtk_widget_queue_draw()' et ses variantes; GTK + vous donnera alors le signal 'draw' quand il pourra le faire. – andlabs

+2

Pour ce que ça vaut, ce modèle de dessin n'est pas unique à GTK +; La plupart des toolkits GUI et des API OS fonctionnent comme ça. La documentation GTK + 3 contient plus d'informations sur les dessins personnalisés éparpillés partout si vous souhaitez en savoir plus. Surtout faites attention aux bits sur l'écrêtage; GTK + ne redessine pas * tout * s'il n'a besoin de mettre à jour qu'une partie du widget. – andlabs

+0

Merci pour l'information andlabs, cela éclaircit certaines choses pour moi. – Arastelion

Répondre

2

Les réponses de andlabs sont correctes. Voici en outre un exemple court (mais pas tout à fait élégant). Il se souviendra des dernières lignes NUM - la création/redimensionnement/activation/désactivation de la fenêtre déclenchera un «tirage» du contenu. Un clic sur un bouton suivant ajoutera une nouvelle ligne à la sortie. Vérifiez également la sortie de la ligne de commande pour une mise à jour de les valeurs de tableau qui sont dessinées.

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

Construire le programme comme d'habitude:

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