2016-05-04 25 views
0

私はゼトコード(http://zetcode.com/gfx/cairo/basicdrawing/)に従っていて、ボタンを押した後に線を描く最初の例を構築しようとしていますが、なぜその理由が分かりません。ボタンをクリックするとsegmentation faultエラーが表示されます。ボタンを押した後にカイロgtk3.0で線を正しく描く方法

enter image description here

PS:私は@jkuのアドバイスに従って、ボタンの状態を記録するためにgboolean draw_a_lineを使用

、およびgtk_widget_queue_draw(ウィジェットを

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

} 

これは、それがどのように見えるかです)を再描画します。私が気づいた唯一の問題は、ボタンをクリックすると即座に描画されないことですが、ウィンドウを非表示にするかウィンドウを引き伸ばして表示する必要があります。私は何らかのautomatic_update()関数を追加する必要があると思うが、私はGUIデザインの初心者だから、ボタンをクリックした直後に行を表示する方法は誰にでも分かるだろうか?

#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をやっているように見えるが、あなたをしていますどこにも通っていない。 – oldtechaa

+0

ありがとうございます!それはその問題でした。 @oldtechaa – daydayup

答えて

2

描画領域(おそらく)に描画ハンドラを作成しましたが、ボタンのクリック信号に接続しました。これら2つの機能シグネチャはまったく異なるため、セグメンテーションは驚きではありません。

ボタンのクリックされたハンドラに直接描画するのではなく、一部のアプリケーションの状態(gboolean should_draw_lineなど)を変更し、gtk_widget_queue_draw()を使用して再描画が必要な描画領域をマークします。描画領域の描画ハンドラで、アプリケーションの状態に基づいて何を描画するかを決定します(should_draw_lineなど)。

あなたがにリンクされている例を見た後、それは `、それに渡された` cairo_t`を持つようになっている()...ほぼ正確に私が提案するもの

+0

ありがとうございました!あなたのアドバイスに沿ってコードを変更した後は、まだ1つの問題があります。私は私のポストを編集しました、あなたは見てみることができますか?もう一度ありがとうございます – daydayup

+0

見た目はほぼ正しいですが、間違ったウィジェット(ボタン)で 'gtk_widget_queue_draw()'を呼びます。それは描画の領域で呼び出す必要があります。なぜなら、これは再描画が必要なためです。 – jku

+0

あなたはあります!私は働いています。ありがとうございます – daydayup

関連する問題