gtk_adjustment_get_value segmentation fault - c

I'm trying to code some simple stuff in C, with GTK+ and Cairo, but I'm having some troubles using the gtk_adjustment_get_value function.
This is my code:
#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;
}
I created a couple of sliders with the hscale widget, and they show up fine in the window, I can move them, everything's alright. But I want to make my variable, pos1x, change when I move the slider. I tried using the gtk_adjustment_get_value function to do it, but I'm getting a segmentation fault. I've noticed that if I comment out this line:
pos1x = gtk_adjustment_get_value (pinfo->adj[0]);
The segmentation fault does not happen anymore, but the app doesn't do what I want either. I realize that this is probably very simple, and my doubts derive from scarce understanding of how GTK+ works, but I've been trying for the last few hours and I can't figure out what's wrong. I'd appreciate any help you have to offer.
Oh, and sorry for putting such a big block of code here, but I wasn't sure which parts you'd need.

You connect to the expose-event here with the userdata pointer set to NULL:
g_signal_connect (window, "expose-event", G_CALLBACK(on_expose_event), NULL);
but in the handler you expect it to be a pointer to ProgInfo. You should replace NULL with pinfo.

Related

Is it possible to put GtkLayouts inside GtkLayout?

I want to put 2 GtkLayouts into GtkLayout. But, it seems to not be working. Anyone knows why ? or, there are some restrictions using gtk components.
#include <gtk/gtk.h>
int main( int argc, char *argv[] )
{
GtkWidget *window, *main_container, *t, *p;
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (window), "layout test");
gtk_window_maximize(GTK_WINDOW(window));
g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK(gtk_main_quit), NULL);
main_container = gtk_layout_new(NULL, NULL);
GdkColor color;
gdk_color_parse ("green", &color);
gtk_widget_modify_bg( GTK_WIDGET(main_container), GTK_STATE_NORMAL, &color);
gdk_color_parse ("red", &color);
t = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(t), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(t), GTK_STATE_NORMAL, &color);
gdk_color_parse ("yellow", &color);
p = gtk_layout_new(NULL, NULL);
gtk_layout_set_size( GTK_LAYOUT(p), 300, 300);
gtk_widget_modify_bg( GTK_WIDGET(p), GTK_STATE_NORMAL, &color);
gtk_layout_put( GTK_LAYOUT(main_container), t, 0, 0 );
gtk_layout_put( GTK_LAYOUT(main_container), p, 0, 300 );
gtk_container_add(GTK_CONTAINER(window), main_container);
gtk_widget_show_all (window);
gtk_main ();
return 0;
}
I found the answer. If the container is appended into another container, it should be treated as a widget. Therefore, uses gtk_widget_set_size_request instead of gtk_layout_set_size will solve this problem.

C LIBCHAMPLAIN SegFault?

I had a programm with C and libchamplain which showed a map. worked fine. Now i wanted to integrate it into an gtk application. But at running, i get a segfault:
#include <stdio.h>
#include <gtk/gtk.h>
#include <champlain/champlain.h>
#include <champlain-gtk/champlain-gtk.h>
#include <clutter-gtk/clutter-gtk.h>
#include <math.h>
#include "GPS_stub.h"
#define MARKER_SIZE 10
#define MAX_SIZ 4096
static gboolean draw_center(ClutterCanvas *canvas, cairo_t *cr, int width, int height){
cairo_set_operator(cr, CAIRO_OPERATOR_CLEAR);
cairo_paint(cr);
cairo_set_operator(cr, CAIRO_OPERATOR_OVER);
cairo_set_source_rgb(cr, 0, 0, 0);
cairo_arc(cr, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, MARKER_SIZE / 2.0, 0, 2 * M_PI);
cairo_close_path(cr);
cairo_set_source_rgba(cr, 0.1, 0.1, 0.9, 1.0);
cairo_fill(cr);
return TRUE;
}
static ClutterActor *create_marker(void){
ClutterActor *marker;
ClutterActor *bg;
ClutterContent *canvas;
ClutterTransition *transition;
marker = champlain_custom_marker_new();
canvas = clutter_canvas_new();
clutter_canvas_set_size(CLUTTER_CANVAS(canvas), MARKER_SIZE, MARKER_SIZE);
g_signal_connect(canvas, "draw", G_CALLBACK(draw_center), NULL);
bg = clutter_actor_new();
clutter_actor_set_size(bg, MARKER_SIZE, MARKER_SIZE);
clutter_actor_set_content(bg, canvas);
clutter_content_invalidate(canvas);
g_object_unref(canvas);
clutter_actor_add_child(marker, bg);
clutter_actor_set_pivot_point(bg, 0.5, 0.5);
clutter_actor_set_position(bg, -MARKER_SIZE, -MARKER_SIZE);
transition = clutter_property_transition_new("opacity");
clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
clutter_transition_set_from(transition, G_TYPE_UINT, 255);
clutter_transition_set_to(transition, G_TYPE_UINT, 0);
clutter_actor_add_transition(bg, "animate-opacity", transition);
transition = clutter_property_transition_new("scale-x");
clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
clutter_transition_set_from(transition, G_TYPE_FLOAT, 0.5);
clutter_transition_set_to(transition, G_TYPE_FLOAT, 1.0);
clutter_actor_add_transition(bg, "animate-scale-x", transition);
transition = clutter_property_transition_new("scale-y");
clutter_actor_set_easing_mode(bg, CLUTTER_EASE_OUT_SINE);
clutter_timeline_set_duration(CLUTTER_TIMELINE(transition), 1000);
clutter_timeline_set_repeat_count(CLUTTER_TIMELINE(transition), -1);
clutter_transition_set_from(transition, G_TYPE_FLOAT, 0.5);
clutter_transition_set_to(transition, G_TYPE_FLOAT, 1.0);
clutter_actor_add_transition(bg, "animate-scale-y", transition);
return marker;
}
static gboolean gps_callback(ChamplainMarker *marker[MAX_SIZ]){
return TRUE;
}
typedef struct{
double lat;
double lng;
} GpsCallbackData;
static void load_map(GpsCallbackData *data){
ClutterActor *actor, *stage;
ChamplainMarkerLayer *layer;
ClutterActor *marker[MAX_SIZ];
stage = clutter_stage_new();
clutter_actor_set_size(stage, 800, 600);
g_signal_connect(stage, "destroy", G_CALLBACK(clutter_main_quit), NULL);
actor = champlain_view_new();
clutter_actor_set_size(CLUTTER_ACTOR(actor), 800, 600);
clutter_actor_add_child(stage, actor);
layer = champlain_marker_layer_new_full(CHAMPLAIN_SELECTION_SINGLE);
clutter_actor_show(CLUTTER_ACTOR(layer));
champlain_view_add_layer(CHAMPLAIN_VIEW(actor), CHAMPLAIN_LAYER(layer));
for(int i = 0; i < MAX_SIZ/40; i++){
marker[i] = create_marker();
champlain_marker_layer_add_marker(layer, CHAMPLAIN_MARKER(marker[i]));
champlain_location_set_location(CHAMPLAIN_LOCATION(marker[i]), data->lat+i/10, data->lng+i/10);
}
g_object_set(G_OBJECT(actor), "zoom-level", 2, "kinetic-mode", TRUE, NULL);
champlain_view_center_on(CHAMPLAIN_VIEW(actor), 40, 0);
g_timeout_add(1000, (GSourceFunc) gps_callback, CHAMPLAIN_MARKER(marker));
clutter_actor_show(stage);
clutter_main();
}
int main(int argc, char *argv[]){
GtkWidget *window, *button;
GpsCallbackData *gps;
double lat, lng;
gtk_clutter_init(&argc, &argv);
hs_init(&argc, &argv);
getGPS("166.82.21.200", &lat, &lng);
printf("GPS: %f %f\n", lat, lng);
gps->lat = lat;
gps->lng = lng;
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
gtk_container_set_border_width(GTK_CONTAINER(window), 10);
button = gtk_button_new_with_label("Load Map");
g_signal_connect(button, "clicked", G_CALLBACK(load_map), &gps);
gtk_container_add(GTK_CONTAINER(window), button);
gtk_widget_show(window);
gtk_main();
hs_exit();
return 0;
}
like you can see in main , it prints out coordinates. This works fine. But then after the printing i'm getting an segfault.
Why?
I have a same problem on ARM Linux from here.
stage = clutter_stage_new();
clutter_actor_set_size(stage, 800, 600);
When I removed or blocked "clutter_actor_set", there's no seg fault error.
actor is O.K, but stage is matter.
But on X86 Ubuntu desktop, it's O.K.

drawing on window using gtk 2.0

I have a program using pthreads. I want add an interface using gtk2.0, but have a problem with drawing on window. When I call g_signal_connect(G_OBJECT(window), "configure_event",G_CALLBACK(draw_things), NULL);
lines which I draw appear and at once disappear. If I move a window calling function
gtk_window_move (GTK_WINDOW(widget), 10,10);
or by means of a mouse, lines appear. If I call g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL); my lines are displayed correctly, but buttons and labels are not displayed. My code looks like this:
int main(int argc, char *argv[]){
pthread_t tr1;
pthread_t tr2;
pthread_t *trs;
int rc = 0;
type j;
int16_t *id;
type Stop_Point;
GtkWidget *window;
GtkWidget *button;
GtkWidget *table;
GtkWidget *drawing_area;
g_thread_init (NULL);
gdk_threads_init ();
gdk_threads_enter ();
gtk_init (&argc, &argv);
window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_widget_set_size_request(window, width/1.6, height/1.33);
gtk_window_set_position(GTK_WINDOW(window), -1);
gtk_window_set_title (GTK_WINDOW (window), "Window");
g_signal_connect (G_OBJECT (window), "delete_event", G_CALLBACK (delete_event), NULL);
gtk_container_set_border_width (GTK_CONTAINER (window), 2);
table = gtk_table_new ( width/1.6, height/1.33, TRUE);
gtk_container_add (GTK_CONTAINER (window), table);
button = gtk_button_new_with_label ("next >>");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1110, 1190, 750, 790);
gtk_widget_show (button);
button = gtk_button_new_with_label ("<< prev");
gtk_table_attach_defaults (GTK_TABLE (table), button, 1020, 1100 , 750, 790);
gtk_widget_show (button);
rc = pthread_create(&tr1, NULL, tr1_func, &id);
rc = pthread_create(&Generator, NULL, tr2_func, &Stop_Point);
trs = (pthread_t*)malloc(Num * sizeof(pthread_t));
for(j = 0; j < Num; j++) {
rc = pthread_create(trs + j, NULL, trs_func, id + j);
}
// g_signal_connect(G_OBJECT(window), "configure-event", GTK_SIGNAL_FUNC(draw_things), NULL);
g_signal_connect(G_OBJECT(window), "expose_event", G_CALLBACK(draw_things), NULL);
gtk_widget_show_all (window);
gtk_main ();
gdk_threads_leave ();
return 0;
}
Fnction for drawing looks like this
gboolean draw_things(GtkWidget *widget, GdkEventExpose *event, gpointer data) {
GdkGC *gc;
gc=gdk_gc_new(GDK_DRAWABLE(widget->window));
gdk_gc_set_line_attributes(gc, 5, GDK_LINE_SOLID, GDK_CAP_ROUND, GDK_JOIN_ROUND);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 5, 35, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 45, 1200, 35);
gdk_draw_line(GDK_DRAWABLE(widget->window), gc, 1170, 25 , 1200, 35);
// gtk_window_move (GTK_WINDOW(widget), 1,1);
return TRUE;
}
Any help is welcomed, because now I use "configure_event" and call gtk_window_move (GTK_WINDOW(widget), 0,0); every time when I need to draw the picture.

How to retrieve input value from GTK spinbutton as float?

I am new to programming as well as GTK and I want to create a GUI for my conic equation program.
How to retrieve inputs from spin button as float ?
void lineG_popup_clicked (GtkButton* button, GtkWidget*){
GtkWidget *popup_window, *button1, *box;
GtkWidget *table,*label,*entry, *entry1, *label1, *label3, *label2, *entry2;
GtkAdjustment *adjustment;
popup_window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
gtk_window_set_title (GTK_WINDOW (popup_window), "Line general formula");
gtk_container_set_border_width (GTK_CONTAINER (popup_window), 10);
gtk_window_set_resizable (GTK_WINDOW (popup_window), FALSE);
gtk_widget_set_size_request (popup_window, 150, 100);
box = gtk_box_new (GTK_ORIENTATION_VERTICAL, 0);
gtk_container_add (GTK_CONTAINER (popup_window), box);
label = gtk_label_new ("Line general formula general:(y = a*x + b )");
gtk_container_add (GTK_CONTAINER (box), label);
table = gtk_table_new(4, 2, TRUE);
gtk_container_add (GTK_CONTAINER (box), table);
adjustment = gtk_adjustment_new (0, 0.0, 10.0, 0.5, 0.1, 0.0);
entry = gtk_spin_button_new(adjustment,1,2);
gtk_table_attach_defaults (GTK_TABLE (table), entry, 1, 2, 1, 2);
label1 = gtk_label_new ("Input the value of a:");
gtk_table_set_homogeneous(GTK_TABLE (table), TRUE);
gtk_table_attach_defaults(GTK_TABLE (table), label1, 0, 1, 1, 2);
adjustment = gtk_adjustment_new (0, 0.0, 10.0, 0.5, 0.1, 0.0);
entry1 = gtk_spin_button_new(adjustment,1,2);
gtk_table_attach_defaults(GTK_TABLE(table), entry1, 1, 2, 2, 3);
label2=gtk_label_new("Input the value of b:");
gtk_table_set_homogeneous(GTK_TABLE(table), TRUE);
gtk_table_attach_defaults(GTK_TABLE (table), label2, 0, 1, 2, 3);
button1 = gtk_button_new_with_label("OK");
gtk_table_set_homogeneous(GTK_TABLE(table), TRUE);
gtk_table_attach_defaults(GTK_TABLE (table), button1, 1, 2, 3, 4);
gtk_widget_show_all (popup_window);
gtk_widget_grab_focus (popup_window);
}
gdouble val = gtk_spin_button_get_value(entry);
That should do it for you! I've found that the API docs are quite helpful, as I too have just started using GTK+

Update multiple progress bar with gtk c++

I need to output the i progress bars and update them all. But only the last one updates i times. This is the code:
static void calculaPi (GtkButton * boton, Datos * dDatos){
const char * threads;
GtkWidget * barra, *bot2, *button, *progress, *vbox;
threads = gtk_entry_get_text(GTK_ENTRY(dDatos->dthreads ));
gint ithreads = 1;
ithreads = atoi(threads);
barra = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title((GtkWindow *) barra, "Loteria de Threads");
gtk_window_set_default_size(GTK_WINDOW(barra), 300, ithreads*30);
gtk_window_set_position(GTK_WINDOW(barra), GTK_WIN_POS_CENTER);
button = gtk_button_new_with_label ("Click me!");
vbox = gtk_vbox_new (FALSE, 5);
gtk_box_pack_start (GTK_BOX (vbox), button, FALSE, FALSE, 5);
gtk_container_add (GTK_CONTAINER (barra), vbox);
for (gint i = 1 ; i <= ithreads; i++) {
progress = gtk_progress_bar_new ();
gtk_box_pack_start (GTK_BOX (vbox), progress, FALSE, FALSE, 5);
g_object_set_data (G_OBJECT (barra), "pbar", (gpointer) progress);
g_signal_connect (G_OBJECT (button), "clicked",
G_CALLBACK (button_clicked), (gpointer) barra);
}
bot2 = gtk_button_new_with_label("Salir");
gtk_box_pack_start (GTK_BOX (vbox), bot2, FALSE, FALSE, 5);
gtk_widget_set_size_request(bot2, 100, 35);
g_signal_connect (G_OBJECT (bot2), "clicked",
G_CALLBACK (destroy),
G_OBJECT (barra));
gtk_widget_show_all(barra);
gtk_main();
}
static void
button_clicked (GtkButton *button,
GtkWidget *barra)
{
GtkProgressBar *progress;
gdouble percent = 0.0;
gtk_widget_set_sensitive (GTK_WIDGET (button), FALSE);
progress = GTK_PROGRESS_BAR (g_object_get_data (G_OBJECT (barra), "pbar"));
while (percent <= 100.0)
{
gchar *message = g_strdup_printf ("%.0f%% Complete", percent);
gtk_progress_bar_set_fraction (progress, percent / 100.0);
gtk_progress_bar_set_text (progress, message);
while (gtk_events_pending ())
gtk_main_iteration ();
g_usleep (500000);
percent += 5.0;
}
}
With this line:
g_object_set_data (G_OBJECT (barra), "pbar", (gpointer) progress);
you override previous value of "pbar" data entry on each loop iteration. When you later retrive it in button_clicked() you get the last set value, i.e. the last progress bar.
In this particular case you can just pass progress widget as user data (and drop g_object_[gs]et_data() calls) for button_clicked() callback: the function doesn't use current barra window for anything else anyway.
In a more general way, you should learn how to use your own structures for user data parameters. A common way is to declare and use one structure for given toplevel type and store pointers to widgets you need to access from callbacks in it.

Resources