2014-01-10 2 views
0

Я пытаюсь закодировать некоторые простые вещи на C, с GTK + и Cairo, но у меня возникают проблемы с использованием функции gtk_adjustment_get_value.gtk_adjustment_get_value segmentation fault

Это мой код:

#include <cairo.h> 
#include <gtk/gtk.h> 
#include <math.h> 
#include <stdlib.h> 
#include <gtk/gtkhscale.h> 
#include <math.h> 

typedef struct 
{ 
    GtkAdjustment *adj[2]; //Adjustments para as escalas 
    GtkWidget *scale[2];  //Escalas 
} ProgInfo; 

gboolean 
on_expose_event (GtkWidget *widget, 
      GdkEventExpose *event, 
     gpointer data) 
{ 
    cairo_t *cr; 
    double pos1x, pos1y; 
    static gdouble pos2x = 450., pos2y = 290.; //Coordenadas Espelho 
    static gdouble pos3x = 450., pos3y = 250.; 
    ProgInfo *pinfo; 

    cr = gdk_cairo_create(widget->window); 

    pinfo = (ProgInfo *) data; 

    pos1x = gtk_adjustment_get_value (pinfo->adj[0]); 

    //Objecto 

    cairo_set_source_rgb (cr, 0, 0, 0); 
    cairo_set_line_width (cr, 1.0); 
    cairo_rectangle (cr, (double) pos1x, (double) pos1y, 20, 80); 
    cairo_stroke_preserve (cr); 
    cairo_set_source_rgb (cr, 1, 1, 1); 
    cairo_fill (cr); 

    cairo_set_source_rgb (cr, 0, 0, 0); 
    cairo_set_line_width (cr, 1.0); 
    cairo_rectangle (cr, (gint) pos3x, (gint) pos3y, 5, 80); 
    cairo_stroke_preserve (cr); 
    cairo_set_source_rgb (cr, 1, 1, 1); 
    cairo_fill (cr); 

    cairo_stroke(cr); 
    cairo_destroy(cr); 

    return FALSE; 
} 


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

    GtkWidget *window, *vbox, *vbox1, *frame, *frame1, *frame2, *label, *label1, *label2, *hbox, *hbox1, *hscale; 
    char string[40] = "Posição Objecto", string1[30] = "Posição Espelho"; 
    ProgInfo *pinfo; 
    gdouble pos1x; 
    pinfo = (ProgInfo *) calloc (1, sizeof (ProgInfo)); 

    gtk_init(&argc, &argv); 

    window = gtk_window_new(GTK_WINDOW_TOPLEVEL); 

    g_signal_connect (window, "expose-event", G_CALLBACK(on_expose_event), NULL); 
    g_signal_connect (window, "destroy", G_CALLBACK(gtk_main_quit), NULL); 

    gtk_window_set_position (GTK_WINDOW(window), GTK_WIN_POS_CENTER); 
    gtk_window_set_title (GTK_WINDOW(window), "Projecto Óptica"); 
    gtk_window_set_default_size (GTK_WINDOW(window), 800, 600); 
    gtk_widget_set_app_paintable (window, TRUE); 

    vbox = gtk_vbox_new (FALSE, 0); 
    gtk_container_add (GTK_CONTAINER (window), vbox); 

    hbox1 = gtk_hbox_new (FALSE, 0); 
    gtk_container_add (GTK_CONTAINER (vbox), hbox1); 

    vbox1 = gtk_vbox_new (FALSE, 0); 
    gtk_box_pack_end (GTK_BOX (hbox1), vbox1, FALSE, FALSE, 20); 

    //Posição Objecto 
    label2 = gtk_label_new (string); 
    gtk_box_pack_start (GTK_BOX (vbox1), label2, FALSE, FALSE, 20); 

    pinfo->adj[0] = (GtkAdjustment *) gtk_adjustment_new (0.7, 0.0, 1.0, 0.001, 1.0, 0.0); 
    //Os parâmetros são, por ordem: valor inicial, valor mínimo e valor máximo 
    pinfo->scale[0] = gtk_hscale_new (GTK_ADJUSTMENT (pinfo->adj[0])); 
    gtk_box_pack_start (GTK_BOX (vbox1), pinfo->scale[0], FALSE, TRUE, 5); 

    //Posição Espelho 
    label1 = gtk_label_new (string1); 
    gtk_box_pack_start (GTK_BOX (vbox1), label1, FALSE, FALSE, 20); 

    pinfo->adj[1] = (GtkAdjustment *)gtk_adjustment_new (0.0, 0.0, 101.0, 0.1, 1.0, 1.0); 
    pinfo->scale[1] = gtk_hscale_new (GTK_ADJUSTMENT (pinfo->adj[1])); 
    gtk_box_pack_start (GTK_BOX (vbox1), pinfo->scale[1], FALSE, FALSE, 0); 

    gtk_widget_show_all(window); 
    gtk_main(); 

    return 0; 
} 

Я создал пару ползунков с hscale виджета, и они отображаются нормально в окне, я могу переместить их, все в порядке. Но я хочу, чтобы моя переменная, pos1x, менялась при перемещении слайдера. Я попытался использовать функцию gtk_adjustment_get_value для этого, но у меня возникает ошибка сегментации. Я заметил, что если я закомментировать эту строку:

pos1x = gtk_adjustment_get_value (pinfo->adj[0]); 

Неисправность сегментации не бывает больше, но приложение не делать то, что я хочу либо. Я понимаю, что это, наверное, очень просто, и мои сомнения возникают из-за недостаточного понимания того, как работает GTK +, но я пробовал последние несколько часов, и я не могу понять, что случилось. Буду признателен за любую помощь, которую вы можете предложить.

О, и извините за то, что вы разместили здесь такой большой блок кода, но я не был уверен, какие части вам понадобятся.

ответ

4

Вы подключаетесь к разоблачить-события здесь с указателем пользовательских данных установлено значение NULL:

g_signal_connect (window, "expose-event", G_CALLBACK(on_expose_event), NULL); 

но в обработчике вы ожидаете, что это будет указатель на ProgInfo. Вы должны заменить NULL на pinfo.