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; /* 次のイベント処理のためループの先頭に飛ぶ */
}
}
}
プログラムができたら、コンパイルして実行してみましょう。
うまく絵が描けましたか?
うまくいった人は以下の応用課題に挑んでみてください。