Check Button Dialog of Programming memorandum


HOME > Check Button Dialog

Check ButtonのDialog

Check Buttonを配置したDialog

チェックボタンが配置されたダイアログについて

checkbutton.png
前頁の”Radio Button Dialog”と同様にどのチェックボタンが押されているかの情報を得たい。
ラジオボタンの場合はただ1個のボタンのONの情報だけで済むが、チェックボタンの場合は複数のボタンについての情報が必要である。
また、どのチェックボタンにもチェックが無い場合の処理も付け加えなければいけない(これは呼び出し側で処理することもできる)
GNOMEではhttps://developer.gnome.org/gnome-devel-demos/stable/checkbutton.c.html.enにチェックボタンに関する例がある。
その他、

コードの要点

(1)チェックボタンが押されたときイベントを検出する関数button_toggled_cb()は、void型とし、グローバル配列変
   数”ck_button[ボタン番号]”に選択されたボタンのON(=1)、OFF(=0)を設定する。したがってcheckbutton_dialog()関数を
   呼び出す前にck_button[]の値を”0”で初期化しておくこと。

どのボタンにチェックが入っているかは、ck_button[]の値で確認する。すべてのボタンが選択されずにOKボタンが押されると困るので、ck_button[]の総和が正の値か否かで少なくとも1つのボタンが選択されていることをチェックした。

(2)checkbutton_dialog()関数はint型とし、ラジオボタンおよび「選択(OK)」、「取消(Cancel)」の2つのボタンを
   配置した。

ダイアログを表示し、GTK_RESPONSE_OKまたはGTK_RESPONSE_CANCELのint値を返す。

(3)チェックボタンはGtkWidget *checkbutton[10]のように配列として作成した。

これはボタンの数がいくつ必要かが事前に分からない場合のためである。たとえば、PC情報を取得した後に、ドライブ情報を表示してデータ消去するドライブの選択をさせる場合、PCにいくつのドライブがついているかは事前に把握できない。

(4)チェックボタンのラベルに設定するデータはファイルからget_list()関数で取得し、list_dat[]に収めた。

checkbutton[]とlist_dat[]を用いて必要な数のチェックボタンを、forループによりダイアログに設定できる。また、対応するイベント関数とのシグナルコネクトと選択ボタンの番号受け渡しを含めて、ループカウンターcountを用いてforループにより機械的に設定できる。なお、checkbutton_dialog()関数の引数にボタンに設定するラベルデータを設定してもよい。私は、ドライブ情報の処理のためにget_list()関数を用いて、呼び出し側でも使用することで、選択データを返り値としてreturnしなくてもよいように処理した。

(5)ラジオボタンのダイアログの場合と同様に、ダイアログ側でエラーチェックとその処理を行っている。

while(1)による無限ループの中で、”result = gtk_dialog_run(GTK_DIALOG(dialog));”による戻り値がある場合、OKかつck_button[]のいずれかが1である場合およびCANCELの場合は、break文で無限ループを抜け、ダイアログを破棄してresurt値を返す。OKかつ選択されたボタンが1つもない場合はshow_warning()で注意を促し、元のチェックボタンのダイアログでの入力を求める仕様である。すなわち、Cancel以外は必ずどれかのチェックボタンを選ばなければいけない仕様である。

error_erase.png


(6)checkbutton_dialog()関数が返すのは(GTK_RESPONSE_OK)または(GTK_RESPONSE_CANCEL)である。

チェックボタンダイアログのコード

/***************************************
    チェックボタンダイアログ
****************************************/
/* グローバル変数の定義 使用するルーチン内で初期化すること*/
static int ck_button[3];/*チェックボタンのON,OFFを記憶する配列。TRUE:1, FALSE:0

/****************************************
    チェックボックスがクリックされるたびに
    ON、OFFのactive状況をチェックして
    ck_button[]にセットON=1,OFF=0
*****************************************/
static void
button_toggled_cb (GtkWidget *checkbutton,
            gpointer user_data)
{
    /*チェックボタンが押されるたびに、このイベントが実行される ON <==> OFF */
    int button_no = GPOINTER_TO_INT(user_data);
    if (gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (checkbutton)))
        ck_button[button_no] = 1;
    else {
        ck_button[button_no] = 0;
    }
}


/*************************************
    チェックボタンのダイアログ表示
*******************************************/
int
checkbutton_dialog(gpointer user_data)
{
    GtkWindow *window = user_data;
    GtkWidget *dialog;

    //get_list関数によりディスク情報を取得
    char list_dat[10][61]; //get_list()関数に与える引数
    char disk_name[disk_MAX][9]; //get_list()関数に与える引数
    int list_count=0; //get_list()関数に与える引数
    get_list(list_dat, disk_name, &list_count);

    //取得したディスク情報をダイアログで表示、チェックボックスで消去対象を選択させる
    GtkWidget *content_area;
    GtkWidget *label;
    GtkWidget *checkbutton[10];//2015/01/06 ボタンの配列化を行う
    GtkDialogFlags flags;
    gint count=0;
    int result=0;
    int i=0;
    int IS_ck_button=0;
    /* dialog windowの作成*/
    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);
    //"_OK"は現行ではAltを押して初めて下線が出る
    /*labelの作成とそれのダイアログのコンテンツエリアへのattach*/
    content_area = gtk_dialog_get_content_area (GTK_DIALOG (dialog));
    label = gtk_label_new ("\n下記からデータを消去するHDDを選択して下さい\n\n ※ 製品名 / サイズ");
    gtk_container_add (GTK_CONTAINER (content_area), label);
    /* 以下、forループでHDDの数だけ設定する */
    for(count = 0; count < list_count; count++){
        checkbutton[count] = gtk_check_button_new_with_label(list_dat[count]);
        gtk_container_add (GTK_CONTAINER (content_area), checkbutton[count]);
        gtk_container_set_border_width(GTK_CONTAINER(checkbutton[count]),2);
        //すべてのボタンの周りにスペース。
        g_signal_connect (GTK_TOGGLE_BUTTON (checkbutton[count]),
                   "clicked",
                    G_CALLBACK (button_toggled_cb),
                    GINT_TO_POINTER(count));
    }

    gtk_widget_show_all (dialog);

    //while文で無限ループ breakで脱出すれば良い1/22
    while(1){
        result = gtk_dialog_run(GTK_DIALOG(dialog));
        for(i=0; i < list_count; i++){//ck_buttonでON(1)の存在を検査
            IS_ck_button +=ck_button[i];
        }
        if(result == GTK_RESPONSE_OK && IS_ck_button == 0 ){//OKかつ選択ナシの場合
            show_warning("処理エラー", "項目が選択されていません", (gpointer) window);
        }
        else{
            break;
        }
    }
    //printf("チェックボックスresult=%d\n",result);
    gtk_widget_destroy(dialog);
    return result;
}


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