2016-05-04 2 views
0

Je suis le code postal (http://zetcode.com/gfx/cairo/basicdrawing/) et en essayant de construire mon premier exemple de dessin d'une ligne après que le bouton est pressé, mais il a échoué et je ne pouvais juste ne comprend pas pourquoi. J'ai une erreur segmentation fault lorsque vous cliquez sur le bouton.comment dessiner correctement une ligne dans Cairo gtk3.0 après avoir appuyé sur un bouton

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

static void do_drawing(cairo_t *); 

static gboolean on_draw_event(GtkWidget *widget, cairo_t *cr, 
    gpointer user_data) 
{ 
    do_drawing(cr); 
    return FALSE; 
} 


static void do_drawing(cairo_t *cr) 
{ 
    cairo_set_source_rgb(cr,0,0,0); 
    cairo_set_line_width(cr,0.5); 

    cairo_move_to(cr,400,400); 
    cairo_line_to(cr,400,200); 

    cairo_stroke(cr); 


} 


int main(int argc, char *argv[]) 
{ 
    GtkWidget *window; 
    GtkWidget *darea; 

    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 480); 
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 

    darea = gtk_drawing_area_new(); 
    GtkWidget *btn_draw = gtk_button_new_with_label("Draw a line"); 


    GtkWidget *mainwindow = gtk_grid_new(); 
     gtk_grid_set_row_spacing (GTK_GRID (mainwindow), 16); 
     gtk_grid_set_column_spacing (GTK_GRID (mainwindow), 16); 
    gtk_grid_set_row_homogeneous(GTK_GRID(mainwindow), TRUE); 
    gtk_grid_set_column_homogeneous(GTK_GRID(mainwindow), TRUE); 

    gtk_widget_set_margin_left(mainwindow,20); 
    gtk_widget_set_margin_right(mainwindow,20); 
    gtk_widget_set_margin_top(mainwindow,20); 
    gtk_widget_set_margin_bottom(mainwindow,20); 

    gtk_grid_attach(GTK_GRID(mainwindow),btn_draw,0,0,1,1); 
    gtk_grid_attach(GTK_GRID(mainwindow),darea,1,0,5,1); 

    gtk_container_add(GTK_CONTAINER(window),mainwindow); 

    g_signal_connect(G_OBJECT(btn_draw),"clicked",G_CALLBACK(on_draw_event),NULL); 

    gtk_widget_show_all(window); 

     gtk_main(); 

     return(0); 

} 

Voici à quoi il ressemble:

enter image description here

PS:

Je suivais des conseils d » de @jku et utiliser un draw_a_line gboolean pour enregistrer l'état du bouton et gtk_widget_queue_draw (widget de) pour redessiner. Le seul problème que j'ai remarqué est que lorsque je clique sur le bouton, il ne dessine pas immédiatement, mais je dois cacher la fenêtre ou étirer la fenêtre pour qu'elle apparaisse. Je pense que je dois ajouter une sorte de fonction automatic_update() mais je suis un débutant à la conception de GUI, donc quelqu'un pourrait-il me dire comment faire apparaître la ligne immédiatement après avoir cliqué sur le bouton?

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

static void do_drawing(cairo_t *); 
GtkWidget *window; 
GtkWidget *darea; 
gboolean draw_a_line = false; 

static gboolean on_draw_event(GtkWidget *widget, GdkEventExpose *event, 
    gpointer user_data) 
{ 
    cairo_t *cr = gdk_cairo_create(gtk_widget_get_window(GTK_WIDGET(widget))); 
    do_drawing(cr); 

    return FALSE; 
} 


static void do_drawing(cairo_t *cr) 
{ 
    cairo_set_source_rgb(cr,0,0,0); 
    cairo_set_line_width(cr,0.5); 
    if (draw_a_line){ 
     cairo_move_to(cr,400,400); 
     cairo_line_to(cr,400,200); 
     cairo_stroke(cr); 
    } 

} 


static void on_clicked(GtkWidget *widget, gpointer data) 
{ 
    draw_a_line = true; 
    gtk_widget_queue_draw(widget); 

} 

int main(int argc, char *argv[]) 
{ 


    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 
    gtk_window_set_default_size(GTK_WINDOW(window), 800, 480); 
    gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER); 

    darea = gtk_drawing_area_new(); 
    GtkWidget *btn_draw = gtk_button_new_with_label("Draw a line"); 


    GtkWidget *mainwindow = gtk_grid_new(); 
     gtk_grid_set_row_spacing (GTK_GRID (mainwindow), 16); 
     gtk_grid_set_column_spacing (GTK_GRID (mainwindow), 16); 
    gtk_grid_set_row_homogeneous(GTK_GRID(mainwindow), TRUE); 
    gtk_grid_set_column_homogeneous(GTK_GRID(mainwindow), TRUE); 

    gtk_widget_set_margin_left(mainwindow,20); 
    gtk_widget_set_margin_right(mainwindow,20); 
    gtk_widget_set_margin_top(mainwindow,20); 
    gtk_widget_set_margin_bottom(mainwindow,20); 

    gtk_grid_attach(GTK_GRID(mainwindow),btn_draw,0,0,1,1); 
    gtk_grid_attach(GTK_GRID(mainwindow),darea,1,0,5,1); 

    gtk_container_add(GTK_CONTAINER(window),mainwindow); 


    g_signal_connect(G_OBJECT(darea), "draw", G_CALLBACK(on_draw_event), NULL); 
    g_signal_connect(G_OBJECT(btn_draw),"clicked",G_CALLBACK(on_clicked),darea); 

    gtk_widget_show_all(window); 

     gtk_main(); 

     return(0); 

} 
+0

'on_draw_event()' est censé avoir un 'cairo_t' qui lui est passé, mais vous êtes ne pas en passer un partout. – oldtechaa

+0

je vous remercie là-bas! c'était ce problème. @oldtechaa – daydayup

Répondre

2

Vous avez écrit un gestionnaire de tirage au sort pour (probablement) la zone de dessin, mais connecté au signal cliqué sur le bouton. Ces deux ont des signatures de fonctions complètement différentes donc une erreur de segmentation n'est pas une surprise. Ne dessinez pas directement sur le gestionnaire cliqué pour le bouton, mais changez l'état de l'application (comme gboolean should_draw_line) et utilisez gtk_widget_queue_draw() pour marquer la zone de dessin comme nécessitant un redessin. Ensuite, dans le gestionnaire de dessin de la zone de dessin, décidez de dessiner en fonction de l'état de l'application (par exemple, should_draw_line).

Après avoir regardé l'exemple vous avez lié, il semble faire presque exactement ce que je suggère ...

+0

Merci monsieur !! C'est vraiment utile, après avoir changé mes codes suite à vos conseils, il y a toujours un problème. J'ai édité mon post, pourriez-vous jeter un coup d'oeil? merci encore – daydayup

+0

Cela semble presque correct mais vous appelez 'gtk_widget_queue_draw()' sur le mauvais widget (le bouton). Vous devriez l'appeler sur la zone de dessin car c'est ce qui nécessite un redessin. – jku

+0

Vous avez eu! Je travail. Merci beaucoup – daydayup