GTK   コントロール

ホーム   C/C++チュートリアル

ラジオボタンで使うイベントは "group_changed" ではなく、 "toggled" でした。2019/12/21に訂正しました。

コントロール


ボタン

このサンプルはGTK3対応です。GTK2ではコンパイルできません。

button.c


#include <gtk/gtk.h>

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *button;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    gtk_window_set_title            (GTK_WINDOW(window), "Button");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    button  = gtk_button_new_with_label ("Quit");
    gtk_widget_set_size_request     (button, 100, 25);
    gtk_widget_set_halign           (button, GTK_ALIGN_CENTER);
    gtk_widget_set_valign           (button, GTK_ALIGN_CENTER);
    gtk_container_add               (GTK_CONTAINER(window), button);
    
    g_signal_connect                (G_OBJECT(button), "clicked",
                                     G_CALLBACK(gtk_main_quit), NULL);
    g_signal_connect                (G_OBJECT(window), "destroy",
                                     G_CALLBACK(gtk_main_quit), NULL);
    
    gtk_widget_show_all(window);
    gtk_main();
    return 0;
}
    

Quit ボタンをクリックしてもアプリケーションが終了します。

コード説明


チェックボタン

このサンプルはGTK3に対応しています。GTK2ではコンパイルできません。

checkbutton.c


#include <gtk/gtk.h>

void toggle_title(GtkWidget *widget, gpointer window);

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *check;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    gtk_window_set_title            (GTK_WINDOW(window),
                                     "CheckButton");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    check   = gtk_check_button_new_with_label   ("Show title");
    gtk_widget_set_halign           (check, GTK_ALIGN_CENTER);
    gtk_widget_set_valign           (check, GTK_ALIGN_CENTER);
    gtk_toggle_button_set_active    (GTK_TOGGLE_BUTTON(check), TRUE);
    
    gtk_container_add               (GTK_CONTAINER(window), check);
    
    g_signal_connect                (G_OBJECT(check), "clicked",
                                     G_CALLBACK(toggle_title), window);
    g_signal_connect                (G_OBJECT(window), "destroy",
                                     G_CALLBACK(gtk_main_quit), NULL);
                                     
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void toggle_title(GtkWidget *widget, gpointer window)
{
    if (gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(widget)))
    {
        gtk_window_set_title(window, "CheckButton");
    } else {
        gtk_window_set_title(window, "");
    }
}
	

実行結果


チェックボタンがチェックされていれば、ウィンドウのタイトルは表示されます。
チェックボタンがチェックされていなければ、ウィンドウのタイトルは表示されません。

コード説明

  1. チェックボタンは、gtk_check_button_new_with_label関数で作ります。 引数にはチェックボタンに表示する文字列を指定します。
  2. gtk_toggle_button_set_active関数でチェックボタンなどの状態を設定できます。 第1引数に対象となるウィジェットを指定して、第2引数にTRUEを指定すると、
    第1引数のオブジェクトがアクティブ状態(チェックされている状態)になります。
  3. チェックボタンと結びつける、g_signal_connect関数の第4引数に、今回は、 widowを渡しています。 これは、呼び出されるtoggle_title関数に第2引数として渡されます。
  4. void toggle_title(GtkWidget *widget, gpointer window)
    gtk_signall_connect関数で呼び出される処理には、呼び出したウィジェットが 自動的に第1引数として渡されます。
  5. gtk_toggle_button_get_active関数は引数で指定したウィジェットの状態を 取得します。


スケール

scale.c


#include <gtk/gtk.h>

void value_changed(GtkRange *range, gpointer label);

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *hbox;
    GtkWidget *scale;
    GtkWidget *label;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    gtk_window_set_title            (GTK_WINDOW(window), "Scale");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    scale   = gtk_scale_new_with_range (GTK_ORIENTATION_HORIZONTAL,
                                     0, 100, 1);
    gtk_scale_set_draw_value        (GTK_SCALE(scale), FALSE);
    label   = gtk_label_new         ("0");
    
    hbox    = gtk_box_new           (GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_box_pack_start              (GTK_BOX(hbox),scale, 1, 1, 0);
    gtk_box_pack_start              (GTK_BOX(hbox),label, 0, 0, 0);
    gtk_widget_set_valign           (hbox, GTK_ALIGN_CENTER);
    gtk_container_add               (GTK_CONTAINER(window), hbox);
    
    g_signal_connect                (scale,  "value-changed",
                                     G_CALLBACK(value_changed), label);
    
    g_signal_connect                (window, "destroy",
                                     gtk_main_quit,             NULL);
    
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void value_changed(GtkRange *range, gpointer label)
{
    gdouble val     = gtk_range_get_value(range);
    gchar   *str    = g_strdup_printf("%.f", val);
    gtk_label_set_text(GTK_LABEL(label), str);
    g_free(str);
}
    

実行結果


スライダーを動かすと、その値がラベルに表示されます。

コード説明

  1. スケールはgtk_scale_new_with_range関数で作ります。引数は次のとおりです。
    1. 第1引数にスケールの向きを定数で指定します GTK_ORIENTATION_HORIZONTALで横向き、 GTK_ORIENTATION_VERTICALで縦向きです
    2. 第2引数はスケールの最小値
    3. 第3引数はスケールの最大値
    4. 第4引数はスケールの刻み幅です
  2. スケールはデフォルトでスライドした位置に現在値が表示される仕組みにいます。
    今回は別の場所に現在値を表示したいのでgtk_set_draw_value関数で現在値が スライドした位置に表示されない設定にします。
    1. 第1引数に対象となるスケール
    2. 第2引数にFALSEを設定します
  3. gtk_box_pack_start関数の第3引数と第4引数の1と0は、 1がTRUEを、0がFALSEを意味しています。 第5引数はウィジェット間のスペースを意味する数値です。
  4. スケールの値が変更された時に発するイベントは、"value-changed"です。
  5. ウィンドウのイベントハンドラーのG_CALLBACKマクロの記述を省略してみました。 問題なさそうですが、気持ちが悪い方は記述してください。
    なおスケールのイベントハンドラーのG_CALLBACKマクロを省略すると、 コンパイル時に警告(warning)が出ます。
  6. void value_changed(GtkRange *range, gpointer label)。 スケールをGtkRange型のポインターとして受け取っています。
  7. gtk_range_get_value関数で引数rangeの現在値を取得できるみたいです。 取得した値をgdoubleというGTKが再定義した型で受け取っていますが
    今回の場合は、double、float、intで受け取っても問題ないみたいです。
  8. g_strdup_printf関数で、数値を文字列に変換した新しい文字列を取得できます。
  9. gtk_label_set_textで、第1引数のラベルに、第2引数の文字列を設定します。
  10. g_free(str)。C言語では、関数が終了する時に内部の変数は破棄され 変数が使用していたメモリーが解放されます。しかしポインターの場合は
    ポインターは破棄されますが、そのポインターが指し示していたアドレスの値は 破棄されません。
    g_free関数を使うと、引数で指定したポインターが指し示すの値の メモリー領域を解放できます。


トグルボタン

togglebutton.c


#include <gtk/gtk.h>

guchar  r = 0;
guchar  g = 0;
guchar  b = 0;

void    draw_callback  ();
void    togglered      ();
void    togglegreen    ();
void    toggleblue     ();
/*
void draw_callback  (GtkWidget *da, cairo_t *cr);
void togglered      (GtkToggleButton *red,   GtkWidget *da);
void togglegreen    (GtkToggleButton *green, GtkWidget *da);
void toggleblue     (GtkToggleButton *blue,  GtkWidget *da);
*/

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *da;
    GtkWidget *red;
    GtkWidget *green;
    GtkWidget *blue;
    GtkWidget *frame;
    GtkWidget *fixed;
    
    gtk_init(&argc, &argv);
    
    window = gtk_window_new         (0);
    gtk_window_set_title            (GTK_WINDOW(window),
                                     "ToggleButton");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    red     = gtk_toggle_button_new_with_label("Red");
    green   = gtk_toggle_button_new_with_label("Green");
    blue    = gtk_toggle_button_new_with_label("Blue");
    da      = gtk_drawing_area_new  ();
    frame   = gtk_frame_new         (NULL);
    gtk_container_add               (GTK_CONTAINER(frame), da);
    gtk_widget_set_size_request     (red,   100,  25);
    gtk_widget_set_size_request     (green, 100,  25);
    gtk_widget_set_size_request     (blue,  100,  25);
    gtk_widget_set_size_request     (da,    110, 110);
    
    fixed   = gtk_fixed_new         ();
    gtk_container_add               (GTK_CONTAINER(window), fixed);
    gtk_fixed_put                   (GTK_FIXED(fixed), red,   20,  20);
    gtk_fixed_put                   (GTK_FIXED(fixed), green, 20,  70);
    gtk_fixed_put                   (GTK_FIXED(fixed), blue,  20, 120);
    gtk_fixed_put                   (GTK_FIXED(fixed), frame,150,  20);
    
    g_signal_connect                (G_OBJECT(da),    "draw",
                                     G_CALLBACK(draw_callback), NULL);
    g_signal_connect                (G_OBJECT(red),   "toggled",
                                     G_CALLBACK(togglered),     da);
    g_signal_connect                (G_OBJECT(green), "toggled",
                                     G_CALLBACK(togglegreen),   da);
    g_signal_connect                (G_OBJECT(blue),  "toggled",
                                     G_CALLBACK(toggleblue),    da);
    g_signal_connect                (window,          "destroy",
                                     gtk_main_quit,             NULL);
                                     
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void draw_callback (GtkWidget *da, cairo_t *cr)
{
    guint width, height;
    GdkRGBA color;
    gchar *rgb;
        
    width = gtk_widget_get_allocated_width (da);
    height = gtk_widget_get_allocated_height (da);
    cairo_rectangle(cr, 0, 0, width, height);
    rgb = g_strdup_printf("rgb(%d,%d,%d)",r, g, b);
    gdk_rgba_parse(&color, rgb);
    g_free(rgb);
    gdk_cairo_set_source_rgba (cr, &color);
    cairo_fill (cr);
    
    //printf("%s\n", gdk_rgba_to_string(&color));
}

void togglered(GtkToggleButton *red, GtkWidget *da)
{
    if (gtk_toggle_button_get_active(red))
    {
        r = 255;
    } else {
        r = 0;
    }
    gtk_widget_queue_draw(da);
}

void togglegreen(GtkToggleButton *green, GtkWidget *da)
{
    if (gtk_toggle_button_get_active(green))
    {
        g = 255;
    } else {
        g = 0;
    }
    gtk_widget_queue_draw(da);
}

void toggleblue(GtkToggleButton *blue, GtkWidget *da)
{
    if (gtk_toggle_button_get_active(blue))
    {
        b = 255;
    } else {
        b = 0;
    }
    gtk_widget_queue_draw(da);
}
	


コード説明

  1. gucharは、再定義されたunsigned charです。
  2. void draw_callback();、プロトタイプの引数は省略できるみたいです。
  3. gtk_toggle_button_new_with_label関数でトグルボタンを作ります。 引数でトグルボタンに表示される文字列を指定します。
  4. gtk_drawing_area_new関数でドローイングエリアを作ります。 ドローイングエリアは様々なグラフィックを描く土台になります。
    引数はありません。 ドローイングエリアには枠線がありませんのでフレームに入れました。
  5. (G_OBJECT(da), "draw"、ドローイングアリアが再描画される時のイベントは "draw"です。
  6. (G_OBJECT(red),"toggled"、トグルボタンが押された時のイベントは "toggled"です。
  7. void draw_callback(GtkWidget *da, cairo_t *cr) ドローイングエリアでイベントが発生した時は 自動的にカイロ(cairo)が引数として送られるみたいです。
    ドローイングエリアはグラフィックスを描画するための土台で カイロが描画を行います。
  8. guint width, height;、guintはGTKで再定義された unsigned intです。
  9. GdkRGBA color;、GTKでカラーを保持する型はGdkRGBAです。
  10. gchar *rgb;、ghar*はGTKで再定義されたchar *です。
  11. gtk_widget_get_allocated_width関数で 引数のウィジェットの横サイズを取得できます。
  12. gtk_widget_get_allocated_height関数で 引数のウィジェットの縦サイズを取得できます。
  13. cairo_rectangle関数で四角形を描きます。第1引数にカイロを、 第2引数に四角形の左上の横位置を、第3引数に四角形の左上の縦位置を、
    第4引数に四角形の横サイズを、第5引数に四角形の縦サイズを指定します。 今回はドローイングエリア一杯に四角形を描いています。
  14. g_strdup_printfは書式指定した文字列を作ります。
  15. gdk_rgba_parseは、第1引数のカラー変数に、第2引数の文字列から分析(parse) した色を入れます。
  16. g_free関数は、引数のポインターが指し示すアドレスのメモリー領域を解放します。 rgbはポインターなので解放しておきます。
  17. gdk_cairo_set_source_rgba関数で、 第1引数のカイロに、第2引数の色を設定します。
  18. cairo_fill関数で引数のカイロのグラフィックスを塗りつぶします。
  19. //printf("%s\n", gdk_rgba_to_string(&color));、 コメントをはずすと、現在の色が rgb(255,0,255)というようにターミナルに表示されます。
  20. void togglered(GtkToggleButton *red, GtkWidget *da)、 トグルボタンのイベントハンドラーが受け取る第1引数の型は
    GTKToggleButtonにした方が良いみたいです。 イベントと結びつける関数のことをイベントハンドラーと言います。
  21. gtk_toggle_button_get_active関数で、引数のトグルボタンが 押された状態がどうかを取得できます。押されていればTRUEです。
  22. gtk_widget_queue_draw関数で引数のウィジェットを再描画できます。
    ドローイングエリアの"draw"イベントは ドローイングエリアが再描画される時に発生します。


ラジオボタン

ラジオボタンで使うイベントは "group_changed" ではなく、 "toggled" でした。2019/12/21に訂正しました。

radiobutton.c


#include <gtk/gtk.h>
//#include <glib.h> //環境によっては必要な場合があります。

void on_toggle();

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *frame;
    GtkWidget *vbox;;
    GtkWidget *hbox;
    GtkWidget *red;
    GtkWidget *green;
    GtkWidget *blue;
    GSList    *group = NULL;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    gtk_window_set_title            (GTK_WINDOW(window),
                                     "RadioButton");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    frame   = gtk_frame_new         ("Red");
    vbox    = gtk_box_new           (GTK_ORIENTATION_VERTICAL,   0);
    hbox    = gtk_box_new           (GTK_ORIENTATION_HORIZONTAL, 0);
    gtk_container_add               (GTK_CONTAINER(window), frame);
    gtk_container_add               (GTK_CONTAINER(frame),  vbox);
    gtk_box_pack_start              (GTK_BOX(vbox), hbox,   1, 0, 0);
    
    red     = gtk_radio_button_new_with_label
                                    (group,                 "Red");
    green   = gtk_radio_button_new_with_label_from_widget
                                    (GTK_RADIO_BUTTON(red), "Green");
    blue    = gtk_radio_button_new_with_label_from_widget
                                    (GTK_RADIO_BUTTON(red), "Blue");
    
    gtk_box_pack_start              (GTK_BOX(hbox), red,    1, 0, 0);
    gtk_box_pack_start              (GTK_BOX(hbox), green,  1, 0, 0);
    gtk_box_pack_start              (GTK_BOX(hbox), blue,   1, 0, 0);
    
    g_signal_connect                (red,           "toggled",
                                     G_CALLBACK(on_toggle),     frame);
    g_signal_connect                (green,         "toggled",
                                     G_CALLBACK(on_toggle),     frame);
    g_signal_connect                (blue,          "toggled",
                                     G_CALLBACK(on_toggle),     frame);
    g_signal_connect                (window,        "destroy",
                                     G_CALLBACK(gtk_main_quit), NULL);
    
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void on_toggle(GtkButton *button, GtkFrame *frame)
{
    const gchar * label = gtk_button_get_label(button);
    gtk_frame_set_label(frame, label);
}
	

実行結果


ラジオボタンをクリックすると、そのラベルが、フレームのラベルになります。

環境によっては次のような警告が出ることがありますが、 結果には影響ありません。


(a.out:2816): Gtk-WARNING **: 20:56:56.165: Could not load a pixbuf from /org/gtk/libgtk/theme/Adwaita/assets/bullet-symbolic.svg.
This may indicate that pixbuf loaders or the mime database could not be found.
    

コード説明

  1. GSList *group = NULL;
    ボタンのグループを登録するためにGSList型のポインターが必要になります。 NULLで初期化しておいたほうが良いみたいです。
    グループに登録されたラジオボタンは、そのグループから一つだけが 選択できるようになります。
  2. frame = gtk_frame_new ("Red");
    フレームを作っています。 引数に文字列を渡すと、その文字列がフレームのラベルとして表示されます。 ラベルが不要な場合には NULL を渡します。
  3. gtk_box_pack_start(GTK_BOX(vbox), hbox, 1, 0, 0);
    第3引数のTRUEを1と、第4引数のFALSEを0と記述しました。 第5引数はもとから数値を記述する場所です。
  4. red = gtk_radio_button_new_with_label(group, "Red");
    ラジオボタンを作っています。第1引数にグループを、 第2引数にラベルに表示される文字列を指定します。
  5. gtk_radio_button_new_with_label_from_widget(GTK_RADIO_BUTTON(red), "Green");
    同じくラジオボタンを作っていますが、今度は 第1引数にグループに登録ずみのラジオボタンを指定します。 こうすることで、同じグループのラジオボタンになります。
    ラジオボタンをグループに追加する方法はいくつかあり、 その中にはもっとラジオボタンとグループの関連性が分かりやすいものもあります。
    しかし今回の方法が、コンパイル時に一番警告(warning)が出ない方法でした。
  6. g_signal_connect(red, "toggled", G_CALLBACK(on_toggle),frame);
    ラジオボタンが選ればれた時のイベントは "toggled" です。 第4引数はNULLではなく、frameを渡しています。 こうすることでイベントハンドラーの第2引数にframeが渡されます。
  7. void on_toggle(GtkButton *button, GtkFrame *frame)
    今回、イベントハンドラーでは、ラジオボタンをGtkButton型で、 フレームをGtkFrame型にしました。
  8. const gchar * label = gtk_button_get_label(button);
    ボタンのラベルを取得しています。この関数は const gchar *型の文字列を返します。
    引数は GTkButton 型でなければコンパイル時に警告が出ます。 そのため、イベントハンドラーの定義でGtkButton型にしました。
  9. gtk_frame_set_label(frame, label);
    この関数で、第1引数のフレームのラベルを、第2引数の文字列にします。 ここでも第1引数は GtkFrame 型でなければコンパイル時に警告がます。
    そのため、イベントハンドラーの定義で、GtkFrame 型にしました。


コンボボックステキスト

comboboxtext.c


#include <gtk/gtk.h>

void combo_selected();

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *combo;
    GtkWidget *label;
    GtkWidget *vbox;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    /* GTK_WINDOW_TOPLEVELは 0 です */
    gtk_window_set_title            (GTK_WINDOW(window),
                                     "ComboBoxText");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    /* GTK_WIN_POS_CENTERは 1 です */
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    combo   = gtk_combo_box_text_new();
    gtk_combo_box_text_append       (GTK_COMBO_BOX_TEXT(combo), NULL,
                                     "Windows");
    gtk_combo_box_text_append       (GTK_COMBO_BOX_TEXT(combo), NULL,
                                     "macOS");
    gtk_combo_box_text_append       (GTK_COMBO_BOX_TEXT(combo), NULL,
                                     "Ubuntu");
    gtk_combo_box_text_append       (GTK_COMBO_BOX_TEXT(combo), NULL,
                                     "Fedora");
    label   = gtk_label_new         ("未選択");
    
    vbox    = gtk_box_new           (1, 0);
    /*GTK_ORIENTATION_HORIZONTALは 0、GTK_ORIENTATION_VERTICALは 1です*/
    gtk_box_pack_start              (GTK_BOX(vbox), combo, 0, 0, 0);
    /* 第3と第4引数はTRUEを1、FALSEを0と記述しています */
    gtk_box_pack_end                (GTK_BOX(vbox), label, 1, 0, 0);
    /* gtk_box_pack_end関数で、後ろから配置することもできます */
    gtk_container_add               (GTK_CONTAINER(window), vbox);
    
    g_signal_connect                (combo,     "changed",
                                     G_CALLBACK(combo_selected),label);
    g_signal_connect                (window,    "destroy",
                                     G_CALLBACK(gtk_main_quit), NULL);
    
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void combo_selected(GtkComboBoxText *combo, GtkLabel *label)
{
    gchar *os;
    os = gtk_combo_box_text_get_active_text(GTK_COMBO_BOX_TEXT(combo));
    gtk_label_set_text(label, os);
    /* label引数をGtkWidget型とし、GTK_LABEL(label)とキャストすることも可 */
    //printf("%s\n", os);
}
	

実行結果


コンボボックステキストで項目を選択すると、 選択された項目の文字列がラベルに表示されます。

コード説明

  1. window = gtk_window_new(0);
    引数の 0 は、GTK_WINDOW_TOPLEVEL定数に定義されている数値です。
  2. gtk_window_set_position(GTK_WINDOW(window), 1);
    第2引数で 1 を指定すると、ウィンドウがスクリーンの中央に表示されます。 1 は、GTK_WIN_POS_CENTER定数に定義されている数値です。
  3. gtk_combo_box_text_new関数でコンボボックステキストを作ります。 ( )はつける必要がありますが、引数はありません。
  4. gtk_combo_box_text_append関数でコンボボックステキストに項目を追加します。
    1. 第1引数に、 GTK_COMBO_BOX_TEXT(combo)の形でコンボボックステキストを指定します
    2. 第2引数に、項目のidを整数で指定します。NULL と指定することもできます
    3. 第3引数に、項目に表示される文字列を指定します
  5. gtk_label_new関数でラベルを作ります。 引数にラベルに表示される文字列を指定します。
  6. gtk_box_new関数でボックスを作ります。 第1引数に横ボックスにするか縦ボックスにするかを 0 か、1 で指定します。
    0 は、GTK_ORIENTATION_HORIZONTA定数に、 1 は、GTK_ORIENTATION_VERTICAL定数に定義されています。
    第2引数には ボックス内に配置されるウィジェット間のギャップ(gap、間隙)を指定します
  7. gtk_box_pack_start関数でボックスにウィジェットを配置します。
    1. 第1引数にボックを指定します
    2. 第2引数に配置するウィジェットを指定します
    3. 第3引数に配置するウィジェットが拡大するかどうかをTRUEかFALSEで指定します TRUEには1が、FALSEには0が定義されています
    4. 第4引数に配置するウィジェットが自分に割り当てられた領域を埋めるがどうかを TRUEかFALSEで指定します
    5. 第5引数に配置するウィジェットの周りのギャップ(gap、間隙)を数値で指定します
  8. gtk_box_pack_end関数は、ボックスの後ろからウィジェットを配置します。 横ボックスでは初めが左で、後ろが右になります。 縦ボックスでは初めが上で、後ろが下になります。
  9. コンボボックステキストの項目が選択された時に発生するイベントは、 "changed" です。
  10. void combo_selected(GtkComboBoxText *combo, GtkLabel *label)
    イベントリスナーでは、コンボボックステキストをGtkComboBoxText型、 ラベルをGtkLabel型で受けています。
  11. gtk_combo_box_text_get_active_text関数は、 引数のコンボボックステキストで現在選択されている項目の文字列を gchar *型で返します。
    イベントハンドラーで combo を GtkWidget 型で受けていた場合は、 GTK_COMBO_BOX_TEXT(combo)とキャストしなければコンパイル時に警告が出ます。
  12. gtk_label_set_text関数は、第1引数のラベルに、第2引数の gchar *型の文字列を設定します。
    イベントハンドラーで label を GtkWidget 型で受けていた場合は、 GTK_LABEL(label)とキャストしなければコンパイル時に警告が出ます。


リストボックス

listbox.c


#include <gtk/gtk.h>

void list_selected();

int main(int argc, char *argv[])
{
    GtkWidget *window;
    GtkWidget *listbox;
    GtkWidget *label;
    GtkWidget *vbox;
    
    gtk_init(&argc, &argv);
    
    window  = gtk_window_new        (0);
    /* GTK_WINDOW_TOPLEVEL定数は 0 です */
    gtk_window_set_title            (GTK_WINDOW(window),
                                     "ListBox");
    gtk_window_set_default_size     (GTK_WINDOW(window), 320, 240);
    gtk_window_set_position         (GTK_WINDOW(window), 1);
    /* GTK_WIN_POS_CENTER定数は 1 です */
    gtk_container_set_border_width  (GTK_CONTAINER(window), 15);
    
    listbox = gtk_list_box_new      ();
    gtk_list_box_insert             (GTK_LIST_BOX(listbox),
                                     gtk_label_new("Windows"),  -1);
    gtk_list_box_insert             (GTK_LIST_BOX(listbox),
                                     gtk_label_new("macOS"),    -1);
    gtk_list_box_insert             (GTK_LIST_BOX(listbox),
                                     gtk_label_new("Ubuntu"),   -1);
    gtk_list_box_insert             (GTK_LIST_BOX(listbox),
                                     gtk_label_new("Fedora"),   -1);
    
    label   = gtk_label_new         (NULL);
    
    vbox    = gtk_box_new           (1, 15);
    /*GTK_ORIENTATION_HORIZONTALは 0、GTK_ORIENTATION_VERTICALは 1です*/
    gtk_box_pack_start              (GTK_BOX(vbox), listbox, 1, 1, 0);
    /* 第3と第4引数はTRUEを1、FALSEを0と記述しています */
    gtk_box_pack_end                (GTK_BOX(vbox), label,   0, 0, 0);
    /* gtk_box_pack_end関数で、後ろから配置することもできます */
    gtk_container_add               (GTK_CONTAINER(window), vbox);
    
    g_signal_connect                (listbox,   "row_selected",
                                     G_CALLBACK(list_selected), label);
                            /* "row-activated"というイベントも使えます */
    g_signal_connect                (window,    "destroy",
                                     G_CALLBACK(gtk_main_quit), NULL);
    
    gtk_widget_show_all             (window);
    gtk_main                        ();
    return                          0;
}

void
list_selected(GtkListBox *list, GtkListBoxRow * row, GtkLabel *label)
{
    GtkWidget *child = gtk_bin_get_child(GTK_BIN(row));
    gtk_label_set_text(label, gtk_label_get_text(GTK_LABEL(child)));
}
	

実行結果


リストボックスで項目を選択すると、 選択された項目の文字列がラベルに表示されます。

コード説明

  1. gtk_list_box_new関数はリストボックスを作ります。引数は必要ありませんが ( )は記述する必要があります。
  2. gtk_list_box_insert(GTK_LIST_BOX(listbox), gtk_label_new("Windows"), -1);
    gkt_list_box_insert関数で リストボックスの指定位置にウィジェットを挿入します。引数は次のとおりです。
    1. 第1引数にリストボックスを指定します
    2. 第2引数にリストに追加するウィジェットを指定します。
    3. 第3引数に挿入する位置を指定します。 -1 を指定するとリストの最後を指定したことになります。
  3. gtk_label_new(NULL) 引数に NULL を渡してラベルを作ることもできます。
  4. gtk_box_new(1, 15) ボックスの方向を 1 (GTK_ORIENTATION_VERTICAL) で、 配置するウィジェット同士の間隙を15でボックスコンテナーを作っています。
  5. gtk_box_pack_start(GTK_BOX(vbox), listbox, 1, 1, 0);
    ボックスにリストボックスを配置しています。引数は次のとおりです
    1. 第1引数にボックスを指定します
    2. 第2引数に配置するウィジェットを指定します
    3. 第3引数に拡大するかどうかをTRUEかFALSEで指定します、 1 はTRUEの意味になります
    4. 第4引数で割り当てられた領域に広がるかどうかを指定します、 1 はTRUEの意味になります
    5. 第5引数にウィジェットの周りの間隙を数値で指定します
  6. g_signal_connect(listbox, "row_selected", G_CALLBACK(list_selected), label);
    リストボックスで項目を選択した時のイベントは "row_selected" です。 "row_activated" イベントも使えます。引数にラベルを渡しています。
  7. void list_selected(GtkListBox *list, GtkListBoxRow * row, GtkLabel *label)
    リストボックスを "row_selected" で接続したイベントハンドラーには、 自動的に、リストボックスと選択されたリストボックスの行が渡されます。
  8. gtk_bin_get_child(GTK_BIN(row))関数で リストボックスの行に設定されたウィジェットが取得できます。
  9. gtk_label_get_text(GTK_LABEL(child))
    上記で取得したウィジェットを、GTK_LABELにキャストして、 gtk_label_get_text関数に渡しています。


10763 visits
Posted: Dec. 16, 2019
Update: Dec. 30, 2019

ホーム   C/C++チュートリアル   目次