How to use GTK signals?

When to define a GTK class, when to use signals?

  • I'm fairly new to GTK, and am messing around with my first "serious" GTK (gtk+-3) app. I'd like to draw on the wisdom of others' experience about when it's suitable to define a new GTK class, or just use a "vanilla" GTK classes, and implement behaviour via signal handlers. I've come across two examples so far: Custom Widgets I'm creating a new widget: basically a GtkDrawingArea, which I use to display some data. I had originally assumed that the best way to implement this would be to subclass GtkDrawingArea, using G_DEFINE_TYPE, and provide my own draw callback: static void mywidget_class_init(MyWidgetClass *klass) { GTK_WIDGET_CLASS(klass)->draw = mywidget_draw; } However, it looks like I could implement exactly the same functionality without defining a new type, by just creating a vanilla GtkDrawingArea, and hooking up the appropriate signals during initialisation. [My custom widget will eventually provide more than just the draw callback, as it needs to be interactive, but that comes later...] Application Windows My application consists of a few different windows, which currently are vanilla GtkWindows: struct myapp_somewindow { struct myapp *app; GtkWindow *window; GtkWidget *some_label_that_is_updated; /*... other window-specific fields */ } When the myapp_somewindow struct is initialised, I create the GtkWindow with gtk_window_new(), and initialise the widgets/layouts/etc, and connect the signals. [I'll probably be using .ui files for the more complex cases eventually, but the windows are simple enough for now.] This could be done my defining a new subclass of GtkWindow, but I'm not certain when the code overhead of defining the new class becomes worthwhile. I'm aware that there's probably no strict rules for which approach to take, but are there any general guidelines to use when making these design decisions? Are there any major pitfalls of either approach?

  • Answer:

    I've worked on a fair few projects using GTK+ and Clutter and i've always promoted heavy use of subclassing of generic widgets / actors to more specific ones. By convention with GObject you create a new file for each class and thus if you pull in the behaviour and state mechanics associated with your widget into a subclass you will pull that code into a separate file. This helps make it easier to structure your code and helps when someone else wants to come along and read it. The subclassing strategy also helps you enforce encapsulation as a good practice on your code base. If your widgets and their associated state and logic are well encapsulated then that can help with reuse. A good example of a project where this subclassing strategy has been used is tasks, and in particular it's internal helper library: http://git.gnome.org/browse/tasks/tree/libkoto This meant that when we wanted to port the application to a new platform or provide a different view on the data it was quite easy to just glue the existing widgets and tree models together in a different way. If you want to use C and you find subclassing a bit tedious then you can try this tool: http://git.gnome.org/browse/turbine/ to help automate the creation of your subclasses.

Jeremy Kerr at Stack Overflow Visit the source

Was this solution helpful to you?

Other answers

I would use the guideline of defining a new class when you need to save some state for the widget. Otherwise, you'll end up creating custom structures holding that state to pass as user data to the signal handlers, making your code more complicated and creating more opportunities for memory leaks. That would suggest that for your second use case, application windows, you should always define a new class. One reason to do it this way is that your widget might start out simple, with behavior that you can implement purely with signal handlers, but later might become more complicated. For example, suppose you want to add a backing store to your drawing area. The "perceived cost" of refactoring your simple widget into a class is high, whereas it'll make your code much cleaner than working around it. Another advantage is that classes can have properties. You can bind these properties to other classes' properties or to GSettings keys, which is a really powerful mechanism and can make your code really simple. If you don't like all the class boilerplate, consider programming in Vala.

ptomato

Find solution

For every problem there is a solution! Proved by Solucija.

  • Got an issue and looking for advice?

  • Ask Solucija to search every corner of the Web for help.

  • Get workable solutions and helpful tips in a moment.

Just ask Solucija about an issue you face and immediately get a list of ready solutions, answers and tips from other Internet users. We always provide the most suitable and complete answer to your question at the top, along with a few good alternatives below.