Re: Separation between GUI and main
Igor Chetverovod <[email protected]>
| Newsgroups | gmane.comp.gnome.glade.user |
|---|---|
| Message-ID | <CAGTgnLdXm6JCAUa7yhxZ9TcyPNDTVBa6zcxCrPPy1aN=i6+ZBg@mail.gmail.com> |
Hello Tristan, Could you please to provide more detailed example for this part of your letter: "...Better practice still, is to derive a GtkContainer for every modular GUI object which can be used and reused throughout your GUI..." ? I am not novice in using of GTK and glade, but I did not catch the work flow of mentioned new technic. It would be great to see a pice of code. Thank you, Igor 2012/1/20, Tristan Van Berkom <[email protected]>: > On Sat, Jan 21, 2012 at 12:44 AM, Manuel Ferrero <[email protected]> wrote: >> I'm learning GTK+ and Glade on my win32 machine. >> >> Right now I was able to write, compile and run a simple code with a >> window, >> an hbox and a toggle button in it. >> When the user presses the button I display the state of the button via the >> callback function. >> >> The main function is this: >> >> ---SNIP--- >> int main(int argc, char *argv[]) >> { >> gtk_init(&argc, &argv); >> >> GtkBuilder *builder_handler; >> GtkWidget *window; >> GtkWidget *connect_button; >> >> builder_handler = gtk_builder_new(); >> gtk_builder_add_from_file(builder_handler, GUI_XML_FILENAME, NULL); >> >> window = GTK_WIDGET(gtk_builder_get_object(builder_handler, "window")); >> connect_button = GTK_WIDGET(gtk_builder_get_object(builder_handler, >> "connect_button")); >> >> gtk_builder_connect_signals(builder_handler, NULL); >> g_object_unref (G_OBJECT (builder_handler)); >> >> gtk_widget_show (connect_button); >> gtk_widget_show (window); >> >> >> gtk_main (); >> >> return 0; >> } // main >> ---PINS--- >> >> I'll spare you the callbacks. >> >> Now my question is this: with Glade I add another button (expanding the >> hbox >> of course) and I name it my_button_2. >> The code has to know about this new button so at least I have to declare a >> new GtkWidget pointer, call the gtk_builder_get_object() to assing the >> pointer and then show it with a gtk_widget_show(). >> Leave alone the callbacks for all the signals. >> >> I don't understand how this can separate the GUI from the code. >> Am I missing something? >> Is tehre some way to connect signals without knowing the objects? In this >> case I could only write the needed callbacks to manage the new button. > > If you need to control the state of a widget in the interface, you need > a pointer to that widget. > > If you add a widget to your interface, say a button that causes a new > action you need to handle, then you don't need a pointer to that button. > > A common practice is to use the last argument of > gtk_builder_connect_signals(), > you can create a data structure which contains the needed pointers for your > whole module, i.e. > > typedef struct _MyModule { > GtkWidget *the_toggle_button; > GtkWidget *the_entry; > GtkWidget *the_toplevel_window; > GtkWidget *etc, *etc; > }; > > { > MyModule module = { 0, }; > > /* where you load the gui file */ > builder = gtk_builder_new (); > gtk_builder_add_from_file (...); > > module.the_toggle_button = gtk_builder_get_object (builder, > "the-toggle-button"); > ... etc etc ... > > /* then just pass your main module structure to all of your callback */ > gtk_builder_connect_signals (builder, &module); > } > > This is common practice but still old-fashioned if you ask me. > > Better practice still, is to derive a GtkContainer for every modular > GUI object which can be used and reused throughout your GUI. > > Then you repeat the above exercise in the object's ->constructed() > method, pass the object's instance as the user data for all callbacks > and have one GtkBuilder xml definition for each composite object > which you might use in your GUI. > > You might have a GUI file describing the layout of your preferences > dialog, your project properties dialog etc. > > Then if you are developing an editor program which might have > multiple projects loaded, you might be allowed to display project > properties dialogs for different projects at the same time. > > Then your properties dialog (which derives from GtkDialog and > has it's contents defined by a GtkBuilder xml file which is added > to the dialog at ->constructor() time)... would have a "project" > property. > > At which point, creating a preferences dialog can be done > at any time with a call to: > new_dialog = g_object_new (MY_TYPE_CUSTOM_PROPERTIES_DIALOG, > "project", > the_project_to_display_properties_for, > NULL); > > Admittedly, with this paradigm, you shouldnt really have to be > doing things by hand in your ->constructor() method... or > accessing GtkBuilder apis manually at all... this is just because > we have not yet landed something at the GtkContainer level > to allow you to simply assign GtkBuilder xml to a container class > (in other words, we are actually still a step behind NextStep > in this respect). > > To answer your question about "separating your GUI from your code", > of course you will always need to declare object members for the > widgets that you actually need to access, adding these members > only ever happens when your program gains new features, and > those features require interaction with the GUI. > > In earlier times, GUIs were constructed in actual code, i.e.: > > window = gtk_window_new(); > box = gtk_box_new (...); > gtk_widget_show (box); > gtk_container_add (GTK_CONTAINER (window), box); > > /* ... huge code to construct menu bar ... */ > gtk_widget_show (menubar); > gtk_container_add (GTK_CONTAINER (box), menubar); > > /* huge code to construct the rest of your application... etc etc */ > > In the first versions of Glade, it was only possible to use with code > generation, > this ended up in the mixing of business logic in generated C code > files, rendering > it virtually impossible to ever modify your GUI after you initially > developped it > (or just very very impractical, because then you have to re-merge in all of > your business logic... just because you wanted to add some icon to a menu > item or add some alignment to a frame or whatever minor detail you wanted > to change). > > Using xml to define the actual interface makes UI coding practical and > maintainable, it separates the files in which you store your code and the > files in which you store your interface definition (note also that you can > always put your GtkBuilder xml into a header file as a string constant > as a step in your compilation, and include the GtkBuilder xml if you > are not content with accessing the hard-drive just to fire up a new > dialog... or if you just want to avoid the complexity of resolving system > installation paths at runtime). > > Cheers, > -Tristan > >> Please remember I'm really new to this programming style, I'm an embedded >> C >> programmer so I know nealry nothign about objects and events. >> >> Thanks in advance. >> -- >> Regards, >> Manuel Ferrero >> R&D department >> >> Reer SpA >> Tel. +39 011 2482215 >> Fax. +39 011 859867 >> >> L'utilizzo non autorizzato del presente messaggio e' vietato e potrebbe >> costituire reato. >> Se il presente messaggio non e' a Lei indirizzato, il suo contenuto non >> deve >> essere considerato >> come trasmesso o autorizzato dalla Reer SpA; in tale caso Le saremmo grati >> se, via e-mail, >> ce ne comunicasse l'errata ricezione. >> >> The unauthorized use of this e-mail is prohibited and could constitute an >> offence. >> If you are not the intended recipient of this message its contents shall >> be >> understood as neither >> given nor endorsed by Reer SpA. Please notify Reer SpA by e-mail >> immediately >> in that case. >> >> _______________________________________________ >> Glade-users maillist - [email protected] >> http://lists.ximian.com/mailman/listinfo/glade-users > _______________________________________________ > Glade-users maillist - [email protected] > http://lists.ximian.com/mailman/listinfo/glade-users > _______________________________________________ Glade-users maillist - [email protected] http://lists.ximian.com/mailman/listinfo/glade-users