2016-05-04 36 views
0

我下面的zetecode(http://zetcode.com/gfx/cairo/basicdrawing/),並試圖建立我按下按鈕後畫線的第一個例子之後,卻失敗了,我真不敢不知道爲什麼。單擊按鈕時出現segmentation fault錯誤。如何正確繪製在開羅gtk3.0線按一個按鈕

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

} 

這是它的外觀:

enter image description here

PS:

我跟着@jku的建議,並使用gboolean draw_a_line錄製按鈕狀態,並gtk_widget_queue_draw(小部件)進行重新繪製。我注意到的唯一問題是,當我單擊按鈕時,它不會立即繪製,但我必須隱藏窗口或拉伸窗口才能顯示。我想我需要添加某種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()'應該有傳遞給它一個'cairo_t',但你不通過任何一個地方。 – oldtechaa

+0

謝謝你!這是這個問題。 @oldtechaa – daydayup

回答

2

你已經寫了一個繪圖處理器(大概)繪製區域,但將它連接到按鈕的單擊信號。這兩個具有完全不同的功能簽名,因此segfault並不意外。

不要直接在按鈕的點擊處理程序上繪圖,而是改變某些應用程序狀態(如gboolean should_draw_line)並使用gtk_widget_queue_draw()將繪圖區域標記爲需要重繪。然後在繪圖區域的繪圖處理程序中根據應用程序狀態決定要繪製什麼(如should_draw_line)。

看着你鏈接到的例子後,它似乎是在做幾乎正是我建議......

+0

謝謝先生!這是非常有幫助的,在我改變我的代碼後,你的建議,它仍然有一個問題。我編輯了我的帖子,你可以看看嗎?感謝ü再次 – daydayup

+0

看起來幾乎正確的,但你打電話'gtk_widget_queue_draw()'在錯誤窗口小部件(按鈕)。您應該在繪圖區域調用它,因爲這需要重繪。 – jku

+0

Got you!我工作。非常感謝你 – daydayup

相關問題