GTK+ learning summary

  1. about naming coventions
    a. All gtk functions or classes(structures) are started with "gtk" or "Gtk" as prefixes. For instance,
      gtk_widget_destroy, GtkLabel, GtkWidget. All glib functions or classese are prefixed with g, for example
      g_signal_connect, g_ascii_strcasecmp, G_OBJECT, g_object_set, g_object_get
    b. The operations for each classes was prefixed by class name. for example, gtk_window_new,
      gtk_button_new_with_label. GtkWindow, GtkLabel
.
    c. All returning types and arguments are pointers to classes. For example, GtkWidget *gtk_window_new(),
      gtk_window_set_title( GtkWindow *window, gchar *str );

    d. All constructor of each classes return the pointer to GtkWidget.
    e. You can covert types using macros. GtkWidget *window; GtkWindow *window = GTK_WINDOW( window );
    f. About signal connecting function, it takes pointer to G_OBJECT only, the final argument gpointer is
      the data you wanna pass into event handling function.
    g. Some event handling function should look like this:
      gboolean event_happened( GtkWidget *widget, GdkEvent *event, gpointer data );
      the first arg widget is the widget which received the signal, event is the event and
      pointer is the data you want to pass.
      Of course, you can use any other form of event handler, like:
      void event_handle( GtkWidget *widget, gpointer data );
      This event handler is much more popular than others
      void event_emitted( GtkWidget *widget1, GtkWidget *widget2 );
      the arguments are pointers. Since you can cast a pointer to any other
      type, so you can replace GtkWidget with any other kind widget you like. Generally, First arg: widget1 is
      the one from which signals are emitted. It is also the widget to which you connect signal. The second
      argument of event handler: widget2, also can be casted to other pointers you like. It is passed from
      final argument of g_signal_connect.
      Sometimes, your handlers must operate more than one widgets. To solve the problem, you can use a structure
      which holds all the necessary widgets. You can pass a pointer to such structure into your handler. E.G.
    typedef struct {
      GtkWindow *window;
      GtkLabel *label;
      GtkButton *button;
    } Data;

      You can connect signal and handler this way:
    g_signal_connect( G_OBJECT( button ), "clicked", G_CALLBACK( button_clicked ),
        (gpointer) &data );

      The handler should look like this:
          void button_clicked( GtkButton *button, Data *data );
    h.For some operations there are more than one function. We get overloading here. But C does not
      support overloading explictly. We solve the problem by adding suffixes to functions indicating
      overloading. e.g.: gtk_button_new(), gtk_button_new_with_label( const char *label ),
      gtk_button_new_with_mnemonic( const char *mnemonic ). They have the same purpose ---- to create
      a new button. Such overloading is quite popular in GTK+.
    i. Once you have add some widgets to some containers, you cannot add it to other containers any more.
      That's why we have to new a label after adding it to a vbox. Adding a widget to a container is make
      the container parent of widget. When releasing the widgets, the child will be released if the parent
      is being freed. Problem occurs when releasing widgets if you add a widgets to more than one container.
      It could be released twice which is a fatal error. As a result, you can never add one widget to more
      than one containers.
    j. There are some internal event handler functions such as destroy -- gtk_widget_destroy. So you can
      connect them directly to destroy(gtk_main_quit), gtk_widget_destroy. It is the same to write it by
      yourself.
    k. Many times, some events have happened, though you have not handled that. A font button, for instance,
      would keep its last font after being clicked. No matter whether you handle the signal 'font_set', it
      would be there until next click. In fact, in your handler, you do nothing but retrieve the current
      also last font from the button and set the font to some widgets. Therefore, it is the same business
      to retrieve the font when we are about to use it.
  2. Tricks about widgets
    1. GtkFileChooser, GtkFileChooserDialog, GtkFileChooserButton
    when you use those widgets, you should handle signal "file_set" rather than others. "file_set" is the
    signal emitted when user do a change of file chooser, i.e. select a file, select another file.
    Signal "selection_changed" will be emitted either when user do a change or when a function change
    the current path. We should use "selection_changed" to monitor file chooser's change. While "file_set"
    is for detecting a file has been selected.
    2. GtkWindow
    If you want to add asking dialog before closing, you should catch signal "delete_event". And the handler's
    prototype should look like this: gboolean before_exit( GtkWidget *, GdkEvent *, gpointer );
        returning FALSE if you don't quit, else return TRUE to quit.
    3. GtkHBox, GtkVBox
    To keep your widgets look homogenous, you have to pack all of them onto boxes. If you pack a hbox and
    a check button onto a vbox, the result is unbalanced. So you'd better arrange all your widgets onto
    boxes.
    4. GtkLabel
    In order to arrange some widgets onto right place, you can use some labels with empty text as a
    placeholder. You want to arrange a button called "Exit", for instance, on the right-down cornor
    of the window, The easiest way to achieve that is place a label unpon button and a label left to
    the button.
    5. GtkFontButton, GtkColorButton, GtkFileChooserButton, and alike.
    They are buttons, right. But they are special buttons. To realize their true mission, you cannot
    treat them as buttons. So you should handle the signal 'font_set', 'color_set' or 'file_set' instead
    of 'clicked'.
        When you are using GtkFileChooserButton, you'd better use event 'selection_change', although it will be
    emitted when setting its properties. The event 'selection_changed' will be emitted when you change a
    selection -- that is when you click the button, select another directory or file. Event 'file_set',
    however, will only be emitted when you click "Others", opening chooser dialog, selecting a file and clicking
    "OK" in dialog. So, if you connect event 'file_set' for it, when you click the folders in the button's list,
    nothing would change. Example: explorerlist.c
    6. GtkToggleButton, GtkRadioButton, GtkCheckButton
    You don't have to write handlers for signal 'toggled'. You can test whether it is active (selected)
    when using the option. If you write a handler, you have to test whether it is active, too, in order to
    set some flag indicating an option.
    7. GtkDialog.
    Dialog is like a window which can hold many things. You can add basic widgets like labels, buttons.
    In addition, you can add GtkAssistant, progress bar, window on it, too. We are happy to say the dialog's
    constructor again:
      GtkWidget *gtk_dialog_new_with_buttons( const char *title, GtkWindow *parent,
      GtkDialogFlag flag, const char *label_button1, int response_button1,
      const char *label_button2, int response_button2, ..., NULL );
    You can use labels from stock like GTK_STOCK_YES, GTK_STOCK_NO, GTK_STOCK_CANCEL, GTK_STOCK_APPLY, etc.
    You can also use some responses predefined by GTK+ like: GTK_RESPONSE_YES, GTK_RESPONSE_NO,
    GTK_RESPONSE_CANCEL, GTK_RESPONSE_APPLY
, etc. There is a container vbox in dialog structure, so
    you can add anything onto it.
    We use the responses of dialog to handle different clicks on buttons, say, returning GTK_RESPONSE_YES means
    button 'Yes' has been clicked, returning GTK_RESPONSE_CANCEL means button 'cancel' has been clicked. A
    typical one is like this:
      
    int result = gtk_dialog_run( GTK_DIALOG( dialog ) );
      if ( result == GTK_RESPONSE_YES ) {
        /* do something */
      } else if ( result == GTK_RESPONSE_NO ) {
        /* do something */
      }
    In general, we would destroy the dialog after clicking one of its buttons by adding:
      gtk_widget_destory( dialog );
    after handling return values.
    At some other times, we want to keep the dialog, because we are not done yet. Some properties panel dialog,
    for example, have three buttons, Cancel, OK and Apply. Clicking Cancel will quit the dialog and do nothing.
    Click OK will apply current settings and quit the dialog. Clicking Apply, however, will apply the settings,
    but don't quit the dialog. For those dialogs, we should put gtk_widget_destroy after GTK_RESPONSE_CANCEL and
    GTK_RESPONSE_OK. But for Apply we should use some other tricks --- we have to keep the dialog and get return
    values, so a while loop is necessary. We usually do like this:
    
      while ( 1 ) {
        result = gtk_dialog_run( GTK_DIALOG( dialog ) );
        if ( result == GTK_RESPONSE_CANCEL ) {
          /* do something */
          gtk_widget_destroy( dialog );
          break;
        } else if (    result == GTK_RESPONSE_OK ) {
          /* do something */
          gtk_widget_destroy( dialog );
          break;
        } else if ( result == GTK_RESPONSE_APPLY ) {
          /* do something */
        }
      }
      We will never leave the dialog unitl 'Cancel' or 'OK' is clicked.
    8. The event handler for signal 'delete-event' of window must be like this:
    static gboolean window_close( GtkWindow *window, GdkEvent *event, gpointer data );
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值