GTK+ Forums

Discussion forum for GTK+ and Programming. Ask questions, troubleshoot problems, view and post example code, or express your opinions.
It is currently Tue Sep 23, 2014 12:21 pm

All times are UTC




Post new topic Reply to topic  [ 5 posts ] 
Author Message
 Post subject: Linking signal handler to function
PostPosted: Sun Apr 29, 2012 9:00 pm 
Offline

Joined: Sun Apr 29, 2012 8:40 pm
Posts: 3
Hello,

I am new to GTK and so, after making some example programs found online, I am trying to make my own.

I wish to use Glade to develop the GUI, and C++ behind the scenes.
I am using Glade version 3.8.0, and Ubuntu Linux

For my first program I have made a GUI in Glade which consists of two text entry boxes, a button, and a label. The ultimate aim is for a user to enter numbers into each of the text boxes, press the button, and the result of their addition is displayed in the label.

To start with I just wish to get a 'reaction' from my button....

Here is my code, cobbled together through my understanding of examples online.......


Code:
#include <gtk/gtk.h>
#include <iostream>

using namespace std;

/* store the widgets which may need to be accessed in a typedef struct */
typedef struct
{
        GtkWidget               *window;
        GtkWidget               *button;
} MyStruct;

gboolean init_app (MyStruct *MyProg);

void on_button1_clicked (GtkButton *button)
{
        cout << "hello!" << endl;
}

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

        MyProg = g_slice_new (MyStruct);

        /* initialize GTK+ libraries */
        gtk_init (&argc, &argv);

        if (init_app (MyProg) == FALSE) return 1; /* error loading UI */

        /* show the window */   
        gtk_widget_show (MyProg->window);

        /* enter GTK+ main loop */                   
        gtk_main ();

        g_slice_free (MyStruct, MyProg);
       
        return 0;
}

gboolean init_app (MyStruct *MyProg)
{
        GtkBuilder              *builder;
       
        /* use GtkBuilder to build our interface from the XML file */
        builder = gtk_builder_new ();
               
       gtk_builder_add_from_file (builder, "experiment.glade", NULL);

        /* get the widgets which will be referenced in callbacks */
        MyProg->window = GTK_WIDGET (gtk_builder_get_object (builder, "window1"));
        MyProg->button = GTK_WIDGET (gtk_builder_get_object (builder, "button1"));
                                                               
        gtk_builder_connect_signals (builder, MyProg);
       
        /* free memory used by GtkBuilder object */
        g_object_unref (G_OBJECT (builder));
                 
        return TRUE;
}


I am compiling it using this command:

Code:
g++ -Wall -g -export-dynamic -o experiment `pkg-config --cflags --libs gtk+-2.0 libglade-2.0` experiment.cpp


As it stands the program runs and my GUI appears on the screen. Unfortunately it is accompanied by a message in the console,

Code:
Gtk-WARNING **: Could not find signal handler 'on_button1_clicked'


I set this signal handler in Glade in the properties window. My understanding is that as long as I use the same function name in my code then it should be able to find it?

What am I doing wrong?

Thanks for any guidance

Jim+


Top
 Profile  
 
 Post subject: Re: Linking signal handler to function
PostPosted: Mon Apr 30, 2012 6:06 am 
Offline
Never Seen the Sunlight

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

You are not doing anything wrong if this was a pure C application. Since your are using C++ all function and variable names under go name mangling which is why the function gtk_builder_connect_signals () can not find the functions to connect the signals to. There are two ways around this, connect the signals manually using g_signal_connect() or mark each signal function with :-
Code:
extern "C"
so that it is visible as a C function and can be found. This does have the disadvantage of losing one of the features of C++, that of function over-loading.

There is a third option of using the gtkmm bindings (a C++ binding to GTK) instead of using the C API directly, this is just an option that is open to you so use which every is most comfortable for you.

As a note in C++ application avoid
Code:
using namespace std;
especially as you code gets bigger and you use more libraries that have their own namespace since you may end up with a name space conflict which the compiler can silently makes its own mind what to do.

Hope that answers your question, and thanks for providing all the needed information. Some people do not even give the language they are using and all the C related languages can look very similar but act very differently.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Linking signal handler to function
PostPosted: Mon Apr 30, 2012 10:52 pm 
Offline

Joined: Sun Apr 29, 2012 8:40 pm
Posts: 3
Hi errol,

Thank you very much for your help.

I think long term I will use gtkmm seeing as it is designed for C++, although as a learning exercise I think I will have a go at creating 2 versions of this project - one using the g_signal_connect() (gtk) method, and one using gtkmm bindings.

A quick google about gtkmm leads me to believe that there is no auto-connect feature with glade produced functions as there is with gtk (without using the extern fix you mention) - is this correct?

To make my project 'fully gtkmm compliant', would I only need to change the way I connect signals, or would I implement all other aspects differently?

Thanks again for your help, it is much appreciated!

Jim+


Top
 Profile  
 
 Post subject: Re: Linking signal handler to function
PostPosted: Tue May 01, 2012 6:40 am 
Offline
Never Seen the Sunlight

Joined: Mon Apr 28, 2008 5:52 am
Posts: 747
Location: UK
You are right that there is no auto-connect feature when using gtkmm. Call-back connection is more complex in C++ due to name mangling, hence the need to use extern "C" if you want this also due to the extra features in C++ which the C API does not have connecting class methods can not be done directly. If you are using classes in gtkmm and want to connect to a class method then things get a little bit more complex as there are now two different ways you can connect your signal.

1 - If your class is derived from a GTK class then you could over-ride one of the signals, a little bit like auto-connecting (this is not always as useful as you may think, although it can be handy when you need it)
2 - Connect the signal manually. There is no direct method of connecting this with a Glade file, even with a work around.

You are better off looking at the documentation and tutorial for gtkmm as it does give you some very good examples see http://developer.gnome.org/gtkmm-tutorial/stable/index.html and for signals http://developer.gnome.org/gtkmm-tutorial/stable/chapter-signals.html.en

I think you main difference will be connecting signals within your own code and not using the Glade feature to do this. Followed by thinking in an object orientated way by using classes and deriving from other objects instead of using shallow structures.

_________________
E.


Top
 Profile  
 
 Post subject: Re: Linking signal handler to function
PostPosted: Fri May 04, 2012 10:47 pm 
Offline

Joined: Sun Apr 29, 2012 8:40 pm
Posts: 3
Thanks errol.

The tutorials look good, I will work through them.

I think I will move away from using glade and just stick to creating the GUI through code. A bit of a shame but I think it will avoid complications once I start trying more 'complex' things.

I have made a simple program using a structure I have seen used quite a bit with simple GTK programs - setting up a widgets class, initialising it immediately when run , and then calling methods of the class to interact with the widgets.

However, I have already run into a question - once I call Gtk::Main::run how can I continue to update my GUI?

In my code below, my second message never gets displayed in the label.

Code:
#include <iostream>
#include <gtkmm.h>

class widgets
{
   Gtk::Window* window;
   Gtk::Label* label;

   public:
      widgets()
      {
         Glib::RefPtr<Gtk::Builder> builder = Gtk::Builder::create_from_file("experiment.glade");

         builder->get_widget("window1", window);
         builder->get_widget("label1", label);
      }

      void show_message(std::string message)
      {
         label->set_label(message);
      }
   
      void run()
      {
         Gtk::Main::run(*window);
      }   
};

int main(int argc,char *argv[])
{
   Gtk::Main kit(argc,argv);

   widgets MyWidgets;
   MyWidgets.show_message("Initial Message");
   MyWidgets.run();
   MyWidgets.show_message("Second Message - I never get displayed :(");
}


Thanks for any guidance.

Jim+


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

All times are UTC


Who is online

Users browsing this forum: Google [Bot] and 1 guest


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:  
cron
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group