Radio Button Dialog of Programming memorandum


HOME > Radio Button Dialog

Radio ButtonのDialog

Radio Buttonを配置したDialog

ネット上のコーディング例についての不満

radiobutton.png
前頁で紹介したサイトで左上の”Contents”を選べば、”GTK+ tutorial”のページに飛び、次の項目が示される。
     Table of contents
         •Introduction
         •First programs
         •Menus and toolbars
         •Layout management
         •Events
         •Dialogs
         •Widgets
         •Widgets II
         •GtkTreeView widget
         •GtkTextView widget
         •Custom GTK+ widget
ここで”Widgets”を選べば、GtkButton、GtkCheckButton、・・・とあるが、コーディングの例にあるのはチェックされたときに、Windowのタイトル表示を"GtkCheckButton"に変更するだけである。
GNOME(https://developer.gnome.org/gnome-devel-demos/stable/checkbutton.c.html.en)におけるコーディングの例も同様である。
ところが、私たちが欲しいのは複数のラジオボタンが設定されているときに、どのボタンが選択されているのかいないのか、それをOKボタンを押したときに知りたいということである。
したがって、ダイアログには複数のラジオボタンとOKボタンがなければいけないし、OKボタンが押されたとき、ONになっているラジオボタンの情報が返ってこなければいけない。

コードの要点

(1)ラジオボタンが押されたとき、イベントを検出する関数button_toggled_cb2()はvoid型とし、グローバル変数”radio_No”に
   選択されたボタンの番号を設定する

(2)radiobutton_dialog()関数はint型とし、ラジオボタンおよび「選択(OK)」、「取消(Cancel)」の2つのボタンを配置した
   ダイアログを表示し、GTK_RESPONSE_OKまたはGTK_RESPONSE_CANCELのint値を返す


(3)ラジオボタンはGtkWidget *button1(~3)のように個別に作成し、配列にはしていない(配列はCheck Buttonの項を参
   照)

(4)「取消(Cancel)」ボタンが押された場合、確認のためにMessage Dialogの項でのshow_question()関数を使用した

   while(1)による無限ループの中で、”result = gtk_dialog_run(GTK_DIALOG(dialog));”による戻り値がCANCELの場合は、
   show_question()により「YES・NO」を問いかけ、YESならば処理を中止し、NOならば無限ループで元のラジオボタン取
   得のダイアログを表示する。

erase_question.png


(5)「選択(OK)」ボタンが押された場合、break文で無限ループを抜け、ダイアログを破棄してresurt値
   (GTK_RESPONSE_OK)を返す

ラジオボタンダイアログのコード

/***************************************
    ラジオボタンダイアログ
****************************************/

static int radio_No;

/**********************************************
    ラジオボタンの選択番号の取得
    グローバル変数:static int radio_No を設定
***********************************************/
static void
button_toggled_cb2 (GtkWidget *radiobutton,
             gpointer user_data)
{
    /*すべてのボタンの状況を知る必要はない 選択中の番号のみ返す*/
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (radiobutton)))
        radio_No = GPOINTER_TO_INT(user_data);
}

/**********************************
ラジオボタンのダイアログ表示
*************************************/
int
radiobutton_dialog(gpointer user_data)
{
    GtkWindow *window = user_data;
    GtkWidget *dialog;
    GtkWidget *content_area;
    GtkWidget *label;
    GtkWidget *button1;
    GtkWidget *button2;
    GtkWidget *button3;

    GtkDialogFlags flags;

    gint count=0;
    int result=0;
    int result2=0;
    flags = GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT;

    dialog = gtk_dialog_new_with_buttons ("TCE HDDの消去方法",
                         GTK_WINDOW(window),
                         flags,
                         "選択(_O)",
                         GTK_RESPONSE_OK,
                         "取消(_C)",
                         GTK_RESPONSE_CANCEL,
                         NULL);
    /*コンテンツエリアをダイアログボックスに作成し、ラベルをコンテンツエリアに追加する*/
    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
    label = gtk_label_new ("\n下記からボタンを選択して下さい\n");
    gtk_container_add (GTK_CONTAINER (content_area), label);

    /*最初のボタンを作成*/
    button1 = gtk_radio_button_new_with_label (NULL, "ボタン(1)");
    gtk_container_add (GTK_CONTAINER (content_area), button1);
    gtk_container_set_border_width(GTK_CONTAINER(button1),2);

    /*2つ目のボタンを最初のボタンと同じグループとして追加・作成*/
    button2 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button1), "ボタン(2)");
    gtk_container_add (GTK_CONTAINER (content_area), button2);
    gtk_container_set_border_width(GTK_CONTAINER(button2),2);

    /*3つ目のボタンを最初のボタンと同じグループとして追加・作成*/
    button3 = gtk_radio_button_new_with_label_from_widget (GTK_RADIO_BUTTON (button1), "ボタン(3)");
    gtk_container_add (GTK_CONTAINER (content_area), button3);
    gtk_container_set_border_width(GTK_CONTAINER(button3),2);

    /*各ボタンの選択状態を設定(ここでは第1のボタンをアクティブに設定)*/
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button1), TRUE);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button2), FALSE);
    gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (button3), FALSE);

    /*シグナルハンドラー(コールバック関数)の各ボタンへの設定。
      GINT_TO_POINTER(0~2)で選択ボタンの番号を伝える*/
    g_signal_connect (GTK_TOGGLE_BUTTON (button1), "toggled",
                G_CALLBACK (button_toggled_cb2), GINT_TO_POINTER(0));
    g_signal_connect (GTK_TOGGLE_BUTTON (button2), "toggled",
                G_CALLBACK (button_toggled_cb2), GINT_TO_POINTER(1));
    g_signal_connect (GTK_TOGGLE_BUTTON (button3), "toggled",
                G_CALLBACK (button_toggled_cb2), GINT_TO_POINTER(2));

    gtk_widget_show_all (dialog);

    /*gtk_dialog_run()を用いてラジオボタンのダイアログを表示。OKかCancelの応答を待つ*/
    while(1){
        result = gtk_dialog_run(GTK_DIALOG(dialog));
        if(result == GTK_RESPONSE_CANCEL){
            /*Cancelの場合の処理:Message DialogのQuestionを用いて処理を分岐 */
            result2 = show_question("確認", "すべての処理を中止しますか?", (gpointer) window);
            if(result2 == GTK_RESPONSE_YES){
                exit(0);
            }
        }
        else{
            /*OKの場合の処理。breakでwhileループを抜ける*/
            break;
        }
    }
    //printf("ラジオボタンを出た\n");
    gtk_widget_destroy(dialog);
    return result;//”GTK_RESPONSE_OK = -5” または ”GTK_RESPONSE_CANCEL = -6” を返す
}

参考
上記のコードは汎用には書かれていない。私が開発用に記したものをそのまま掲載したものである。特に、while(1)ループでCancelの場合の確認をする部分がそうである。
この部分は呼び出し側で行ってもよい部分である。その場合は、result = gtk_dialog_run(GTK_DIALOG(dialog));を残して他のwhile()ループ内のコードを削除して、gtk_widget_destroy(dialog);とreturn result;につなげばよい。
使用法
工事中。