バッキングボックスを使って二つのボタンをウィンドウに貼り付ける


ウィンドウウェジェットに直接貼り付けられるウェジェットは1つに限られています。
そこで、いくつでもウェジェットの貼り付けが可能なバッキングボックスというインターフェースを一枚用意し、それをウィンドウウェジェットに張るようにします。


#include<gtk/gtk.h>

int main(int argc, char *argv[]){
GtkWidget *window;

//gtk+を初期化
gtk_init(&argc, &argv);

//ウィンドウェジェットを作成
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

//ウィンドウの大きさを指定
gtk_widget_set_size_request(window, 600, 400);

//パッキンボックスを作成
GtkWidget *vbox;
vbox = gtk_vbox_new(FALSE,2);

//パッキンボックスをwindowに貼り付ける
gtk_container_add(GTK_CONTAINER(window), vbox);


//ボタンを作成
GtkWidget *button1;
button1 = gtk_button_new_with_label("quit");

//ボタンをクリックした時のコールバック関数を登録
g_signal_connect(G_OBJECT(button1), "clicked", G_CALLBACK(gtk_main_quit),NULL);

//button1をvboxの上半分に貼り付ける
gtk_box_pack_start(GTK_BOX(vbox), button1, TRUE, TRUE, 0);


//ボタンを作成
GtkWidget *button2;
button2 = gtk_button_new_with_label("quit");

//ボタンをクリックした時のコールバック関数を登録
g_signal_connect(G_OBJECT(button2), "clicked", G_CALLBACK(gtk_main_quit),NULL);

//button2をvboxの下半分に貼り付ける
gtk_box_pack_start(GTK_BOX(vbox), button2, TRUE , TRUE, 0);

//ウィンドを閉じたときにプログラムを終了するようにコールバックする。
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

//ウィンドウ上のウェジェットをすべて表示(gtk_widget_show_all)
gtk_widget_show_all(window);

gtk_main();

return 0;
}



コールバック関数

前回のプログラムはウィンドウ左上のバツ印をクリックしてもプログラムが終了しませんでした。

そこで、コールバック関数を登録して、バツ印をクリックすればプログラムが終了するようにします。

/* gtk_test.c*/

#include<gtk/gtk.h>

int main(int argc, char *argv[]){
GtkWidget *window;

//gtk+を初期化
gtk_init(&argc, &argv);

//ウィンドウェジェットを作成
window=gtk_window_new(GTK_WINDOW_TOPLEVEL);

//ウィンドウの大きさを指定
gtk_widget_set_size_request(window, 600, 400);

//ウィンドを閉じたときにプログラムを終了するようにコールバックする。
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);

//ウィンドウを表示
gtk_widget_show(window);

gtk_main();

return 0;
}



GTK+を使った最小GUIアプリ

GTK+を使ったプログラミングに手を出してみました。

まずはGTK+をインストール
$ sudo apt-get update
$ sudo apt-get install libgtk2.0-dev


#以下はソースコード
$ vim gtk_test.c

/* gtk_test.c */

#include <gtk/gtk.h>
#include<stdlib.h>

int main(int argc, char *argv[]){
GtkWidget *window;

/* GTK+の初期化とオプション解析 */
gtk_init(&argc, &argv);


/* ウィンドウの作成 */
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);


/* ウィンドウの表示 */
/* The GTK_WINDOW_TOPLEVEL argument specifies that we want the window 
  to undergo window manager decoration and placement. */
gtk_widget_show_all(window);


/* メインループ */
/* gtk_main() is another call you will see in every GTK application. 
When control reaches this point, 
GTK will sleep waiting for X events (such as button or key presses), 
timeouts, or file IO notifications to occur. In our simple example, however, events are ignored. */
gtk_main();

exit(0)
}




#GTK+を利用したプログラムをコンパイルした時は、特殊なオプションをつける必要がある。
$ gcc    -o  gtk_test gtk_test.c `pkg-config --cflags --libs gtk+-2.0`"

#毎回このように長いオプションを入力するのは面倒なので以下のようにエイリアスを作成し

$ alias gccgtk="gcc `pkg-config --cflags --libs gtk+-2.0`"
$ gccgtk -o gtk_test gtk_test.c

#プログラムを実行
$ ./gtk_test.c







renameを使って、mvコマンドを作る

ファイルを移動するAPIはrename()である。
/* mymv.c */

#include<stdio.h> /* fprintf, perror, rename */
#include<stdlib.h> /* exit */
#include<unistd.h>

/*
#inclde<stdio.h>
int rename(const char *old, const char *new);
*/

int main(int argc, char *argv[])
{
        if(argc != 3){
                fprintf(stderr, "%s: wrong arguments\n", argv[0]);
                exit(1);
        }
        if(rename(argv[1], argv[2]) < 0){
                perror(argv[1]);
                exit(1);
        }
        exit(0);
}

#実行例
$ gcc -o mymv mymv.c
$ touch testfile
$ mymve

./mymv: wrong arguments
$ mv testfile TEST
$ ls
TEST mymv mymv.c

opendir, readdir, closedirを駆使して、lsコマンドを作る


ディレクトリ操作の基本であるopendir, readdir, closedirの基本的な使い方について勉強しました。



/* myls.c */

#include<stdio.h> /* fprintf */
#include<stdlib.h> /* exit */
#include<sys/types.h> /* opendir readdir closedir */
#include<dirent.h> /* opendir readdir closedir */

/*
#include<sys/types.h>
#include<dirent.h>
DIR *opendir(const char *path);

#include<sys/types.h>
#include<dirent.h>
struct dirent *readdir(DIR *d);

#include<sys/types.h>
#include<dirent.h>
int closedir(DIR *d);

*/

static void do_ls(char *path);

int main(int argc, char *argv[])
{
int i;
/*コマンドライン引数が無いときは、stderrにコメントを出力*/
if(argc <2){
fprintf(stderr, "%s: no arguments\n", argv[0]);
exit(1);
}

for(i = 1; i< argc; i++){
do_ls(argv[i]);
}
exit(0);
}


static void do_ls(char *path)
{
DIR *d;
struct dirent *ent;
/* pathにあるディレクトリを読み込むために開く。戻り値はDIRという型へのポインタ。*/
d = opendir(path);
if(!d){
perror(path);
exit(1);
}
/*ディレクトリストリームdからエントリを一つずつ読み込む。
読み込んだエントリをstruct direntで返す。
ディレクトリエントリは、ディレクトリの中身の情報を含んだ構造体。
 */
while(ent = readdir(d)){
fprintf(stdout,"%s  ", ent->d_name);
}
/*ディレクトリストリームを閉じる*/
closedir(d);
fprintf(stdout,"\n");
}