GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Thu Oct 23, 2014 2:27 pm

All times are UTC




Post new topic Reply to topic  [ 12 posts ] 
Author Message
 Post subject: update a label in realtime when clicking a radio button?
PostPosted: Wed Feb 17, 2010 5:35 pm 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
Hi, I have a problem changing a label in realtime when a user clicks on a radio button.
It works so far that after clicking a radio button the user has to re-enter the data into the entry then it updates the label.
I get a crash on the line 42 and 52.

Code:
//compile: gcc -Wall -g ./ref1b.c -o ref1b `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0`  && ./ref1b

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

const float minute = 60.0;
const float hour = 60.0;
const float day = 24.0;
const float week = 7.0;
const float month = 30.0;
const float year = 365.0;

long double distance=1;
long double speed;
long double x_distance;
char totalready[80];

gboolean delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
   return FALSE;
}

static void destroy (GtkObject *object, gpointer data)
{
   gtk_main_quit();
}

static void clicked_call_back(GtkRadioButton *rb, GtkWidget *entry, gpointer label)
{
   const gchar * label_str;
   if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rb)))
   {
      distance = 1;

      label_str = gtk_entry_get_text(GTK_ENTRY(entry));
      long double number1 = strtod(label_str, NULL);
      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance);
      //gtk_label_set_text(GTK_LABEL(label), totalready); // <-Crash
   }   
   else
   {
      distance = distance*946080000*10000;

      label_str = gtk_entry_get_text(GTK_ENTRY(entry));
      long double number1 = strtod(label_str, NULL);
      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance);
      //gtk_label_set_text(GTK_LABEL(label), totalready); // <-Crash
   }
}

static void update (GtkWidget *entry, GdkEventKey *event, gpointer label)
{
   const gchar * label_str;
   if ( (int) g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(entry)), -1) != 0)
   {
      label_str = gtk_entry_get_text(GTK_ENTRY(entry));
      long double number1 = strtod(label_str, NULL);

      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance);
      gtk_label_set_text(GTK_LABEL(label), totalready);
   }
   else
      gtk_label_set_text(GTK_LABEL(label), NULL);
}

int main(int argc, char *argv[])
{
   GtkWidget *window, *instruct, *label, *entry, *box, *radio_button_1, *radio_button_2;
   gtk_init (&argc, &argv);
   
   window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_default_size(GTK_WINDOW(window), 400, 100);
   gtk_container_set_border_width(GTK_CONTAINER(window),10);
   gtk_window_set_urgency_hint(GTK_WINDOW(window), TRUE);
   gtk_window_set_title(GTK_WINDOW(window),"Space Travel");
   gtk_widget_show(window);
   
   g_signal_connect(G_OBJECT(window), "delete_event", G_CALLBACK(delete), NULL);
   g_signal_connect(G_OBJECT(window), "destroy", G_CALLBACK(destroy), NULL);
   
   box = gtk_vbox_new (FALSE, 0);
   gtk_container_add(GTK_CONTAINER(window), box);

   instruct = gtk_label_new ("Enter your distance:");               
   gtk_box_pack_start (GTK_BOX (box), instruct, TRUE, TRUE, 5);

   entry = gtk_entry_new();
   gtk_box_pack_start (GTK_BOX (box), entry, TRUE, TRUE, 5);
   gtk_widget_grab_focus(entry);

   radio_button_1 = gtk_radio_button_new_with_label(NULL, "in light-years");
   gtk_box_pack_start(GTK_BOX(box), radio_button_1, TRUE, TRUE, 5);

   radio_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(radio_button_1), "in km/h");
   gtk_box_pack_start(GTK_BOX(box), radio_button_2, TRUE, TRUE, 5);

   label = gtk_label_new (NULL);
   gtk_box_pack_start (GTK_BOX (box), label, TRUE, TRUE, 5);

   g_signal_connect(G_OBJECT(entry), "key-release-event", G_CALLBACK(update), (gpointer) label);
   g_signal_connect(G_OBJECT(radio_button_2), "clicked", G_CALLBACK(clicked_call_back), (gpointer) entry);

   gtk_widget_show_all(GTK_WIDGET(window));
   gtk_main ();   
   return 0;
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 6:38 am 
Offline
Familiar Face

Joined: Wed Oct 21, 2009 5:21 am
Posts: 24
Location: India
In line no:107 you are passing the pointer of 'entry' only. But in the callback function you try to access the label which causes the crashing.

If you need to send more than one variable, you have to create a structure containing the variables and pass a pointer to that structure.

I did some work on your code. I create the structure of all items created in main.
Hope it can help you.

Code:
//compile: gcc -Wall -g ./ref1b.c -o ref1b `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0`  && ./ref1b

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

const float minute = 60.0;
const float hour = 60.0;
const float day = 24.0;
const float week = 7.0;
const float month = 30.0;
const float year = 365.0;

long double distance = 1;
long double speed;
long double x_distance;
char totalready[80];

typedef struct
{
   GtkWidget *window;
   GtkWidget *instruct;
   GtkWidget *label;
   GtkWidget *entry;
   GtkWidget *box;
   GtkWidget *radio_button_1;
   GtkWidget *radio_button_2;
} GtkObj;

gboolean delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
    return FALSE;
}

static void destroy (GtkObject *object, gpointer data)
{
    gtk_main_quit();
}

static void clicked_call_back(GtkRadioButton *rb, GtkObj *object)
{
    const gchar * label_str;
    if( gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rb)))
    {
        distance = 1;

        label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
        long double number1 = strtod(label_str, NULL);
        x_distance = number1 * distance;
        sprintf(totalready, "%16Lf", x_distance);

       gtk_label_set_text(GTK_LABEL(object->label), totalready); // <-Won't Crash
    }   
    else
    {
        distance = distance*946080000*10000;

        label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
        long double number1 = strtod(label_str, NULL);
        x_distance = number1 * distance;
        sprintf(totalready, "%16Lf", x_distance);

        gtk_label_set_text(GTK_LABEL(object->label), totalready); // <-Won't Crash
    }
}

static void update (GtkWidget *entry, GdkEventKey *event, gpointer label)
{
    const gchar * label_str;
    if ( (int) g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(entry)), -1) != 0)
    {
        label_str = gtk_entry_get_text(GTK_ENTRY(entry));
        long double number1 = strtod(label_str, NULL);

        x_distance = number1 * distance;
        sprintf(totalready, "%16Lf", x_distance);
        gtk_label_set_text(GTK_LABEL(label), totalready);
    }
    else
        gtk_label_set_text(GTK_LABEL(label), NULL);
}

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

   GtkObj *obj;

    gtk_init (&argc, &argv);
   
    obj->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(obj->window), 400, 100);
    gtk_container_set_border_width(GTK_CONTAINER(obj->window),10);
    gtk_window_set_urgency_hint(GTK_WINDOW(obj->window), TRUE);
    gtk_window_set_title(GTK_WINDOW(obj->window),"Space Travel");
    gtk_widget_show(obj->window);
   
    g_signal_connect(G_OBJECT(obj->window), "delete_event", G_CALLBACK(delete), NULL);
    g_signal_connect(G_OBJECT(obj->window), "destroy", G_CALLBACK(destroy), NULL);
   
    obj->box = gtk_vbox_new (FALSE, 0);
    gtk_container_add(GTK_CONTAINER(obj->window), obj->box);

    obj->instruct = gtk_label_new ("Enter your distance:");               
    gtk_box_pack_start (GTK_BOX (obj->box), obj->instruct, TRUE, TRUE, 5);

    obj->entry = gtk_entry_new();
    gtk_box_pack_start (GTK_BOX (obj->box), obj->entry, TRUE, TRUE, 5);
    gtk_widget_grab_focus(obj->entry);

    obj->radio_button_1 = gtk_radio_button_new_with_label(NULL, "in light-years");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_1, TRUE, TRUE, 5);

    obj->radio_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_1), "in km/h");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_2, TRUE, TRUE, 5);

    obj->label = gtk_label_new (NULL);
    gtk_box_pack_start (GTK_BOX (obj->box), obj->label, TRUE, TRUE, 5);

    g_signal_connect(G_OBJECT(obj->entry), "key-release-event", G_CALLBACK(update), (gpointer) obj->label);
    g_signal_connect(G_OBJECT(obj->radio_button_2), "clicked", G_CALLBACK(clicked_call_back), (gpointer) obj);

    gtk_widget_show_all(GTK_WIDGET(obj->window));
    gtk_main ();   
    return 0;
}


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 7:45 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
Pretty good solution, but obj is not initialised on line 88 and its use latter on would cause a crash. Changing that line to allocate the memory would solve that.

Code:
    GtkObj *obj = g_new(GtkObj, 1);


E.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 7:57 am 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
ah, got it, thanks! :D

there is another problem: when the program starts and i enter something in the entry it seems that, although the top radio button is automatically selected at the start, it doesn't change the label result (it only changes if i reselect this radio button)

*edit*
thank you, errol :)


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 8:38 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
Not really a GTK problem, but what value you initialise "distance" to.

So just change your initialisation of distance to this and it should be what you expect.

Code:
long double distance=946080000.0*10000.0;


E.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 8:58 am 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
I thought it's a GTK related problem because it somehow doesn't refresh the radio button at the start, thanks.

*edit*
The program isn't done yet. let me see if I can port this completely from my c code :D I'll then post it here or in Project Showcase forum if it's ok.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 9:07 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
The signal that is connect to your radio is the "clicked" and will only be activated when the user clicks on it. I think there is a way using the "show" signal, but it probably is easier just to initialise all your variables to the correct values and set you widgets to the correct state.

E.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 18, 2010 1:30 pm 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
errol: I tried some of these but didn't work

Code:
  void (* enter)    (GtkButton *button);
  void (* leave)    (GtkButton *button);
  void (* activate) (GtkButton *button);

Now that the program is completely ported from c and not being able to set a radio button status at start, save or check the status of the radio buttons the problem is visible and quite annoying.
Check it out, any solutions?

Code:
//compile: gcc -Wall -g ./ref1c.c -o ref1c `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0`  && ./ref1c

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

const float minute = 60.0;
const float hour = 60.0;
const float day = 24.0;
const float week = 7.0;
const float month = 30.0;
const float year = 365.0;

long double distance=946080000.0*10000.0;
long double speed=300000.0;
long double x_distance;
long double x_time;
char totalready[80];

typedef struct
{
   GtkWidget *window;
   GtkWidget *instruct, *instruct2;
   GtkWidget *label, *entry, *entry2;
   GtkWidget *box;
   GtkWidget *radio_button_1, *radio_button_2, *radio_button_3, *radio_button_4;
} GtkObj;

gboolean delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
   return FALSE;
}

static void destroy (GtkObject *object, gpointer data)
{
   gtk_main_quit();
}

static void clicked_callback_radio_button(GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_2)))
   {
      distance = 1;

      label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
      long double number1 = strtod(label_str, NULL);
      x_distance = number1 * distance/speed/minute/hour/day/year;
      sprintf(totalready, "%16Lf", x_distance);

      x_label_str = g_strconcat("Travel time in years (debug: \"in km\" RB was last pressed): ", totalready, NULL);

      //how to track the status of radio button 3 and 4 to display only if radio button 3 or 4 was clicked
      //also (how to) set automatically the radio button 3 or 4 when program starts
      //save the status of radio buttons in a variable
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
   }   
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_1)))
   {
      distance = distance*946080000.0*10000.0;

      label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
      long double number1 = strtod(label_str, NULL);
      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

      x_label_str = g_strconcat("Travel time in years (debug: \"in light-years\" RB was last pressed): ", totalready, NULL);

      //how to track the status of radio button 3 and 4 to display only if radio button 3 or 4 was clicked
      //also (how to) set automatically the radio button 3 or 4 when program starts
      //save the status of radio buttons in a variable
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
   }
}

static void clicked_callback_radio_button2(GtkRadioButton *rb, GtkObj *object)
{
   gchar * x_label_str = NULL;
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(rb)))
   {
      gtk_entry_set_text(GTK_ENTRY(object->entry2), "");
      gtk_widget_set_sensitive(object->entry2, FALSE);

      speed=300000.0;
      sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

      x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
   }
   else
   {
      gtk_widget_set_sensitive(object->entry2,TRUE);
      gtk_label_set_text(GTK_LABEL(object->label), "");      
   }
}

static void clicked_callback_entry (GtkWidget *entry, GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;
   if ( (int) g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(object->entry)), -1) != 0)
   {
      label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
      long double number1 = strtod(label_str, NULL);

      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

      x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
   }
   else
      gtk_label_set_text(GTK_LABEL(object->label), NULL);
}

static void clicked_callback_entry2 (GtkWidget *entry, GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;

   
   label_str = gtk_entry_get_text(GTK_ENTRY(object->entry2));
   long double speed__entry2 = strtod(label_str, NULL);

   speed__entry2 = speed__entry2/(minute*hour);
   sprintf(totalready, "%16Lf", x_distance/speed__entry2/minute/hour/day/year);

   x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);

   gtk_label_set_text(GTK_LABEL(object->label), x_label_str);

   g_free(x_label_str);
}

int main(int argc, char *argv[])
{
   GtkObj *obj = g_new(GtkObj, 1);

   gtk_init (&argc, &argv);
   
   obj->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_default_size(GTK_WINDOW(obj->window), 580, 100);
   gtk_container_set_border_width(GTK_CONTAINER(obj->window),10);
   gtk_window_set_urgency_hint(GTK_WINDOW(obj->window), TRUE);
   gtk_window_set_title(GTK_WINDOW(obj->window),"Space Travel");
   gtk_widget_show(obj->window);
   
   g_signal_connect(G_OBJECT(obj->window), "delete_event", G_CALLBACK(delete), NULL);
   g_signal_connect(G_OBJECT(obj->window), "destroy", G_CALLBACK(destroy), NULL);
   
   obj->box = gtk_vbox_new (FALSE, 0);
   gtk_container_add(GTK_CONTAINER(obj->window), obj->box);

   obj->instruct = gtk_label_new ("Enter your distance:");               
   gtk_box_pack_start (GTK_BOX (obj->box), obj->instruct, TRUE, TRUE, 5);

   obj->radio_button_1 = gtk_radio_button_new_with_label(NULL, "in light-years");
   gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_1, TRUE, TRUE, 5);

   obj->radio_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_1), "in km");
   gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_2, TRUE, TRUE, 5);


   obj->entry = gtk_entry_new();
   gtk_box_pack_start (GTK_BOX (obj->box), obj->entry, TRUE, TRUE, 5);
   gtk_widget_grab_focus(obj->entry);


   obj->instruct2 = gtk_label_new ("Enter your speed:");               
   gtk_box_pack_start (GTK_BOX (obj->box), obj->instruct2, TRUE, TRUE, 5);

   obj->radio_button_3 = gtk_radio_button_new_with_label(NULL, "in speed-of-light");
   gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_3, TRUE, TRUE, 5);

   obj->radio_button_4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_3), "in km/h");
   gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_4, TRUE, TRUE, 5);


   obj->entry2 = gtk_entry_new();
   gtk_widget_set_sensitive( obj->entry2, FALSE );
   gtk_box_pack_start (GTK_BOX (obj->box), obj->entry2, TRUE, TRUE, 5);
   gtk_widget_grab_focus(obj->entry2);


   obj->label = gtk_label_new (NULL);
   gtk_box_pack_start (GTK_BOX (obj->box), obj->label, TRUE, TRUE, 5);

   g_signal_connect(G_OBJECT(obj->entry), "key-release-event", G_CALLBACK(clicked_callback_entry), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->radio_button_2), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->radio_button_3), "clicked", G_CALLBACK(clicked_callback_radio_button2), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->entry2), "key-release-event", G_CALLBACK(clicked_callback_entry2), (gpointer) obj);

   gtk_widget_show_all(GTK_WIDGET(obj->window));
   gtk_main ();   
   return 0;


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 21, 2010 11:43 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 764
Location: UK
Hi,

I have rewritten your code a fair bit, to try and make it simpler and clearer to read. I also took the liberty to redefine some of your astronomical constants :-)

The first thing that I have done place displaying of the travel time in one function, which is then called from other places. This should make future modifications to your code easier as there is only one place where travel time is displayed and calculated instead of many. The only new function that I have used is g_strdup_printf(), which you can think of as a sprintf(), but putting the result in an allocated bit of memory.

Next there is a reduction in the number of callback functions. The callback clicked_callback_radio_button() is call whenever any one of the radio buttons is clicked on. All that callback now does is find out which button is active, set the relevant variable and calls dis_travel_time(). The callback clicked_callback_entry() now only calls dis_travel_time().

I hope all this is clear, and shows that you can set many callbacks calling the same function.

Code:
//compile: gcc -Wall -g ./ref1c.c -o ref1c `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0`  && ./ref1c

#include <gtk/gtk.h>
#include <glib/gprintf.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

const float minute = 60.0;
const float hour = 60.0;
const float day = 24.0;
const float week = 7.0;
const float month = 30.0;
const float year = 365.25;

long double distance=9.4607305e12;
long double speed=299792.458;

typedef struct
{
    GtkWidget *window;
    GtkWidget *instruct;
    GtkWidget *instruct2;
    GtkWidget *label;
    GtkWidget *entry;
    GtkWidget *entry2;
    GtkWidget *box;
    GtkWidget *radio_button_1;
    GtkWidget *radio_button_2;
    GtkWidget *radio_button_3;
    GtkWidget *radio_button_4;
} GtkObj;

gboolean delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
    return FALSE;
}

static void destroy (GtkObject *object, gpointer data)
{
    gtk_main_quit();
}

/*
* Get the distance and speed from the entries and calculate the
* travel time in years. Then display it in the label.
*/

static void dis_travel_time(GtkObj *obj)
{
    long double dis;
    long double sp;
    gchar *label_str = NULL;

    const gchar *s = gtk_entry_get_text(GTK_ENTRY(obj->entry));
    dis = strtod(s, NULL);

    s = gtk_entry_get_text(GTK_ENTRY(obj->entry2));
    sp = strtod(s, NULL);

    label_str = g_strdup_printf("Travel time in years : %16Lf", (dis * distance)/speed/sp/minute/hour/day/year);
    gtk_label_set_text(GTK_LABEL(obj->label), label_str);
    g_free(label_str);
}

/*
* All clicks on the radio buttons come here.
* We just work out which one is active and set the speed and
* distance variables. After which we call dis_travel_time()
* to display a newly caluated travel time.
*/

static void clicked_callback_radio_button(GdkEventKey *event, GtkObj *object)
{
    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_1)))
        distance = 9.4607305e12;
    else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_2)))
        distance = 1.0;

    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_3)))
        speed = 299792.458;
    else if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_4)))
        speed = 1.0 / minute / hour;

    dis_travel_time(object);
}

/*
* All button presses on the entries come here.
* All we do is call dis_travel_time() to display the travel time.
*/

static gboolean clicked_callback_entry (GtkWidget *entry, GdkEventKey *event, GtkObj *object)
{
    dis_travel_time(object);

    return FALSE;
}

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

    gtk_init (&argc, &argv);

    obj = g_new(GtkObj, 1);   
    obj->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
    gtk_window_set_default_size(GTK_WINDOW(obj->window), 580, 100);
    gtk_container_set_border_width(GTK_CONTAINER(obj->window),10);
    gtk_window_set_urgency_hint(GTK_WINDOW(obj->window), TRUE);
    gtk_window_set_title(GTK_WINDOW(obj->window),"Space Travel");
   
    g_signal_connect(G_OBJECT(obj->window), "delete_event", G_CALLBACK(delete), NULL);
    g_signal_connect(G_OBJECT(obj->window), "destroy", G_CALLBACK(destroy), NULL);
   
    obj->box = gtk_vbox_new (FALSE, 0);
    gtk_container_add(GTK_CONTAINER(obj->window), obj->box);

    obj->instruct = gtk_label_new ("Enter your distance:");               
    gtk_box_pack_start (GTK_BOX (obj->box), obj->instruct, TRUE, TRUE, 5);

    obj->radio_button_1 = gtk_radio_button_new_with_label(NULL, "in light-years");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_1, TRUE, TRUE, 5);

    obj->radio_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_1), "in km");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_2, TRUE, TRUE, 5);


    obj->entry = gtk_entry_new();
    gtk_box_pack_start (GTK_BOX (obj->box), obj->entry, TRUE, TRUE, 5);

    obj->instruct2 = gtk_label_new ("Enter your speed:");               
    gtk_box_pack_start (GTK_BOX (obj->box), obj->instruct2, TRUE, TRUE, 5);

    obj->radio_button_3 = gtk_radio_button_new_with_label(NULL, "in speed-of-light");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_3, TRUE, TRUE, 5);

    obj->radio_button_4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_3), "in km/h");
    gtk_box_pack_start(GTK_BOX(obj->box), obj->radio_button_4, TRUE, TRUE, 5);


    obj->entry2 = gtk_entry_new();
    gtk_box_pack_start (GTK_BOX (obj->box), obj->entry2, TRUE, TRUE, 5);

    obj->label = gtk_label_new (NULL);
    gtk_box_pack_start (GTK_BOX (obj->box), obj->label, TRUE, TRUE, 5);

    g_signal_connect(G_OBJECT(obj->entry), "key-release-event", G_CALLBACK(clicked_callback_entry), (gpointer) obj);
    g_signal_connect(G_OBJECT(obj->entry2), "key-release-event", G_CALLBACK(clicked_callback_entry), (gpointer) obj);

    g_signal_connect(G_OBJECT(obj->radio_button_1), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);
    g_signal_connect(G_OBJECT(obj->radio_button_2), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);
    g_signal_connect(G_OBJECT(obj->radio_button_3), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);
    g_signal_connect(G_OBJECT(obj->radio_button_4), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);

    gtk_widget_show_all(GTK_WIDGET(obj->window));

    gtk_main ();

    g_free(obj);

    return 0;



E.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Feb 21, 2010 3:28 pm 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
Hi, errol and thanks for the nice code.
The only thing I would change when the user clicks on the 3rd radio button: the maximal value allowed for entry2 is 1 because nothing is faster than the speed of light.

Oh and the other thing, I put the widgets in table (2x7) like the code below so the radio buttons are parallel (hbox-like, but didn't work as I tried so I tried table.)

But how to allow only entering "1" as maximal value ? any defined functions?

Also: My internal trying of solving the bug was this code from yesterday but this doesn't solve the problem completely because I wasn't done with the coding and your code is much better now.

Code:
//compile: gcc -Wall -g ./ref1c.c -o ref1c `pkg-config --cflags gtk+-2.0 --libs gtk+-2.0`  && ./ref1c

#include <gtk/gtk.h>
#include <stdlib.h>
#include <stddef.h>
#include <stdio.h>
#include <string.h>

const float minute = 60.0;
const float hour = 60.0;
const float day = 24.0;
const float week = 7.0;
const float month = 30.0;
const float year = 365.0;

long double distance=946080000.0*10000.0;
long double speed=300000.0;
long double x_distance;
long double x_time;
char totalready[80];
short int last_selected_radio_button=0;

typedef struct
{
   GtkWidget *window;
   GtkWidget *instruct;
   GtkWidget *instruct2;
   GtkWidget *label;
   GtkWidget *entry;
   GtkWidget *entry2;
   GtkWidget *table;
   GtkWidget *radio_button_1;
   GtkWidget *radio_button_2;
   GtkWidget *radio_button_3;
   GtkWidget *radio_button_4;
} GtkObj;

gboolean delete (GtkWidget *widget, GdkEvent *event, gpointer data)
{
   return FALSE;
}

static void destroy (GtkObject *object, gpointer data)
{
   gtk_main_quit();
}

static void clicked_callback_radio_button(GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;
   if ( (int) g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(object->entry)), -1) != 0 )
   {
      if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_2)))
      {
         distance = 1;

         label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
         long double number1 = strtod(label_str, NULL);
         x_distance = number1 * distance/speed/minute/hour/day/year;
         sprintf(totalready, "%16Lf", x_distance);

         x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);

         gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
      }   
      if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_1)))
      {
         distance = distance*946080000.0*10000.0;

         label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
         long double number1 = strtod(label_str, NULL);
         x_distance = number1 * distance;
         sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

         x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);

         gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
      }
   }
}

static void clicked_callback_radio_button2(GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_3)))
   {
      gtk_entry_set_text(GTK_ENTRY(object->entry2), "");
      gtk_widget_set_sensitive(object->entry2, FALSE);

      label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
      long double number1 = strtod(label_str, NULL);

      x_distance = number1 * distance;

      speed=300000.0;
      sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

      x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);

      last_selected_radio_button=3;
   }
   if(gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(object->radio_button_4)))
   {
      gtk_widget_set_sensitive(object->entry2,TRUE);
      gtk_label_set_text(GTK_LABEL(object->label), "");

      last_selected_radio_button=4;
   }
}

static void clicked_callback_entry (GtkWidget *entry, GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;
   if ( (int) g_utf8_strlen(gtk_entry_get_text(GTK_ENTRY(object->entry)), -1) != 0 && last_selected_radio_button!=4)
   {
      label_str = gtk_entry_get_text(GTK_ENTRY(object->entry));
      long double number1 = strtod(label_str, NULL);

      x_distance = number1 * distance;
      sprintf(totalready, "%16Lf", x_distance/speed/minute/hour/day/year);

      x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);
      gtk_label_set_text(GTK_LABEL(object->label), x_label_str);
   }
   else
      gtk_label_set_text(GTK_LABEL(object->label), NULL);
}

static void clicked_callback_entry2 (GtkWidget *entry, GdkEventKey *event, GtkObj *object)
{
   gchar * x_label_str = NULL;
   const gchar * label_str;

   
   label_str = gtk_entry_get_text(GTK_ENTRY(object->entry2));
   long double speed__entry2 = strtod(label_str, NULL);

   speed__entry2 = speed__entry2/(minute*hour);
   sprintf(totalready, "%16Lf", x_distance/speed__entry2/minute/hour/day/year);

   x_label_str = g_strconcat("Travel time in years: ", totalready, NULL);

   gtk_label_set_text(GTK_LABEL(object->label), x_label_str);

   g_free(x_label_str);
}

int main(int argc, char *argv[])
{
   GtkObj *obj = g_new(GtkObj, 1);

   gtk_init (&argc, &argv);
   
   obj->window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
   gtk_window_set_default_size(GTK_WINDOW(obj->window), 400, 100);
   gtk_container_set_border_width(GTK_CONTAINER(obj->window),10);
   gtk_window_set_urgency_hint(GTK_WINDOW(obj->window), TRUE);
   gtk_window_set_title(GTK_WINDOW(obj->window),"Space Travel");
   gtk_widget_show(obj->window);
   
   g_signal_connect(G_OBJECT(obj->window), "delete_event", G_CALLBACK(delete), NULL);
   g_signal_connect(G_OBJECT(obj->window), "destroy", G_CALLBACK(destroy), NULL);
   
   obj->table = gtk_table_new (7, 2, TRUE);
   gtk_container_add(GTK_CONTAINER(obj->window), obj->table);

   obj->instruct = gtk_label_new ("Enter your distance:");             
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->instruct, 0, 2, 0, 1);

   obj->radio_button_1 = gtk_radio_button_new_with_label(NULL, "in light-years");
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->radio_button_1, 0, 1, 1, 2);

   obj->radio_button_2 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_1), "in km");
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->radio_button_2, 1, 2, 1, 2);

   obj->entry = gtk_entry_new();
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->entry, 0, 2, 2, 3);
   gtk_widget_grab_focus(obj->entry);

   obj->instruct2 = gtk_label_new ("Enter your speed:");
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->instruct2, 0, 2, 3, 4);

   obj->radio_button_3 = gtk_radio_button_new_with_label(NULL, "in speed-of-light");
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->radio_button_3, 0, 1, 4, 5);

   obj->radio_button_4 = gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(obj->radio_button_3), "in km/h");
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->radio_button_4, 1, 2, 4, 5);

   obj->entry2 = gtk_entry_new();
   gtk_widget_set_sensitive(obj->entry2, FALSE);
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->entry2, 0, 2, 5, 6);
   gtk_widget_grab_focus(obj->entry2);

   obj->label = gtk_label_new (NULL);
   gtk_table_attach_defaults (GTK_TABLE (obj->table), obj->label, 0, 2, 6, 7);

   g_signal_connect(G_OBJECT(obj->entry), "key-release-event", G_CALLBACK(clicked_callback_entry), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->radio_button_2), "clicked", G_CALLBACK(clicked_callback_radio_button), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->radio_button_3), "clicked", G_CALLBACK(clicked_callback_radio_button2), (gpointer) obj);
   g_signal_connect(G_OBJECT(obj->entry2), "key-release-event", G_CALLBACK(clicked_callback_entry2), (gpointer) obj);

   gtk_widget_show_all(GTK_WIDGET(obj->window));

   gtk_main ();
   
   return 0;
}


Top
 Profile  
 
 Post subject:
PostPosted: Sat Feb 27, 2010 1:16 am 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
Ok I set "1" as the start value for entry2 so far as a "solution" but the next question is how can I center the program's window at the start?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Mar 13, 2010 4:52 pm 
Offline
Familiar Face

Joined: Wed Feb 17, 2010 5:18 pm
Posts: 9
Ok, I solved it, thanks all.

http://www.gtkforums.com/viewtopic.php?p=14245


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 12 posts ] 

All times are UTC


Who is online

Users browsing this forum: Google Adsense [Bot], Yahoo [Bot] and 4 guests


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group