Previous: 前回の復習
Up: Xウィンドウ実習
第6回 少し複雑なイベント処理

Previous Page: 前回の復習
Next Page: Xウィンドウ実習
第7回 ペイントツール(その2)
色や線をボタンで選択

複数のウィンドウからのイベント

アプリケーションが複雑になり、ウィンドウの数が増えてくると イベント処理のループが少しややこしくなります。
この例では3個のウィンドウからのイベントを処理しなくてはなりません。 まず、canvas からマウスのドラッグイベントを受け取り その動きに合わせて絵を描く処理を行ないます。 また、quit でマウスがクリックされたらプログラムの終了の処理が、 clear でマウスがクリックされたらキャンバスのクリア処理が、 それぞれ呼び出されるようにします。
下のようにイベントループの中がかなり長くなりますが、 ウィンドウごとに処理を分けることにすれば 見やすくなるでしょう。 ソース・ファイル名は paint1.c としてください。

paint1.c

#include<stdio.h>
#include<X11/Xlib.h>
main()
{
 Display *dsp;                       /* ディスプレイ構造体の宣言 */
 Window   frame;                     /* ウィンドウ構造体の宣言 */
 Window   canvas, command;
 Window   quit, clear;
 GC       gc;                        /* GC構造体の宣言 */
 XEvent   eve;                       /* イベント構造体の宣言 */
 int x1, y1, x2, y2;                 /* 線の座標を記憶する変数 */

dsp = XOpenDisplay( NULL ); /* ディスプレイのオープン */

/* ウィンドウの生成 */ frame = XCreateSimpleWindow( dsp, DefaultRootWindow(dsp), 0, 0, 600, 400, 1, BlackPixel(dsp,0), BlackPixel(dsp,0) ); canvas = XCreateSimpleWindow( dsp, frame, 5, 5, 555, 355, 0, BlackPixel(dsp,0), WhitePixel(dsp,0) ); command = XCreateSimpleWindow( dsp, frame, 565, 265, 30, 95, 0, BlackPixel(dsp,0), WhitePixel(dsp,0) ); quit = XCreateSimpleWindow( dsp, command, 2, 5, 24, 24, 1, BlackPixel(dsp,0), WhitePixel(dsp,0) ); clear = XCreateSimpleWindow( dsp, command, 2, 35, 24, 24, 1, BlackPixel(dsp,0), WhitePixel(dsp,0) );

gc = XCreateGC( dsp, canvas, NULL, NULL ); /* GCの生成 */ XSetForeground( dsp, gc, BlackPixel(dsp,0) );

/* イベントマスクの設定 */ XSelectInput( dsp, canvas, ButtonPressMask | Button1MotionMask ); XSelectInput( dsp, quit, ButtonPressMask | ExposureMask ); XSelectInput( dsp, clear, ButtonPressMask | ExposureMask );

XStoreName( dsp, frame, "Paint Tool" ); /* タイトルの設定 */

/* ウィンドウの表示 */ XMapWindow( dsp, frame ); XMapSubwindows( dsp, frame ); XMapSubwindows( dsp, command );

XFlush( dsp );

/* イベント処理の無限ループの開始 */ while( True ) { XNextEvent( dsp, &eve ); /* 新しいイベントを受け取る */

if( eve.xany.window == canvas ) /* イベントが canvas で発生 */ { switch( eve.type ) { case ButtonPress: /* マウス・ボタンが押された瞬間の処理 */ switch( eve.xbutton.button ) { case 1: x1=eve.xbutton.x; y1=eve.xbutton.y; break; default: break; } break; case MotionNotify: /* マウスをドラッグ中の処理 */ x2=eve.xbutton.x; y2=eve.xbutton.y; XDrawLine( dsp, canvas, gc, x1, y1, x2, y2 ); x1=x2; y1=y2; break; default: break; } continue; /* 次のイベント処理のためループの先頭に飛ぶ */ }

if( eve.xany.window == clear ) /* イベントが clear で発生 */ { switch( eve.type ) { case ButtonPress: /* クリックされた時の処理 */ XClearWindow( dsp, canvas ); /* キャンバスのクリア */ break; case Expose: /* 再表示の処理 */ XDrawString( dsp, clear, gc, 4, 16, "Cls", 3 ); break; default: break; } continue; /* 次のイベント処理のためループの先頭に飛ぶ */ }

if( eve.xany.window == quit ) /* イベントが quit で発生 */ { switch( eve.type ) { case ButtonPress: /* クリックされた時の処理 */ XCloseDisplay( dsp ); /* ディスプレイのクローズ */ exit(0); /* 終了 */ case Expose: /* 再表示の処理 */ XDrawString( dsp, quit, gc, 2, 16, "Quit", 4 ); break; default: break; } continue; /* 次のイベント処理のためループの先頭に飛ぶ */ } } }


プログラムができたら、コンパイルして実行してみましょう。 うまく絵が描けましたか?

うまくいった人は以下の応用課題に挑んでみてください。

maruyama@wakhok.ac.jp
1995年02月01日 (水) 00時21分18秒 JST