イベント処理

ここでは、ユーザーがGUIコンポーネントを操作した際に処理を行う、「イベント処理」について解説します。

- 目次 -

イベント駆動プログラミング

これまでは、プログラムを実行すると、あらかじめ決まりきった処理の流れに基づいて、処理が行われてきました。

一方、GUIを用いたプログラムでは、ユーザーがボタンをクリックしたり、マウスを動かしたりした時 に、それぞれに対応した処理を行う必要があります。 「いつ処理されるか」は決められないため、「何かが起こった時に処理する」という形に、処理の流れの考え方を変える必要があるわけです。

このような処理を扱うための仕組みの一つが、「イベント駆動プログラミング」です。VCSSLのGUIの処理は、典型的なイベント駆動プログラミングの仕組みを採用しています。

イベントとは

イベントとは、「何かが起こった時に処理する」における、「起こった何か」を指す用語です。 そして、その「何かが起こった」という事を、「イベントが発生した」と言います。

例えば、「ユーザーがボタンをクリックした」とか、「マウスが操作された」といった事がイベントです。

イベントハンドラ関数

さて、イベントが発生すると、それに対応する関数がシステム側から呼ばれます。 このような関数の事を一般に「イベントハンドラ関数」と呼びます。

イベントハンドラ関数の模式図。
イベントハンドラの概念図
「ボタンがクリックされる」などのイベントが発生すると、イベントハンドラ関数が実行される。

イベントハンドラ関数の内容はあらかじめ用意されているのではなく、プログラムの書き手が自由な内容を記述します。

特定の名前と引数の関数を宣言するだけでOK、登録不要

VCSSLでは、 処理したいイベントの種類に応じて特定の関数名と引数を持たせると、 それが自動的にイベントハンドラ関数と見なされ、イベント発生時に呼び出されます。 特別な登録処理などを行う必要はありません。

イベントハンドラ関数の仕様に共通する特徴

VCSSLのイベントハンドラ関数は、以下のように共通した特徴を持っています:

ここからは、実際に様々な種類のイベントと、イベントハンドラ関数の仕様を見ていきましょう。

ウィンドウイベント処理

ウィンドウに関するイベントを処理するには、以下のイベントハンドラ関数を使用します。

イベントハンドラ関数 引数 イベント
onWindowOpen int id ウィンドウが起動した際に呼び出されます。
onWindowClose int id ウィンドウが閉じた際に呼び出されます。
onWindowMove int id,
int x,
int y
ウィンドウが動いた際に呼び出されます。
onWindowResize int id,
int width,
int height
ウィンドウサイズが変わった際に呼び出されます。
onWindowShow int id ウィンドウが表示された際に呼び出されます。
onWindowHide int id ウィンドウが非表示になった際に呼び出されます。

引数は以下の通りです:

ここで特に重要なのがonWindowClose関数です。 このイベントハンドラ関数内で exit() 関数をコールするようにすると、 一般的なソフトウェアのような「 ウィンドウを閉じると処理を終了する 」という機能を実現できます。

これまで、VCSSLプログラムを終了させるには、 VCSSLコンソールを手動で閉じるしかありませんでした。 しかし、ウィンドウを閉じればプログラムが自動終了するようにしておけば、 VCSSLコンソールは不要なので、hide() 命令で隠してしまっても問題ありません。

ボタンイベント処理

ボタンに関するイベントを処理するには、以下のイベントハンドラ関数を使用します。

イベントハンドラ関数 引数 イベント
onButtonClick int id,
string text
ボタンがクリックされた際に呼び出されます。

引数は以下の通りです:

セレクトフィールドイベント処理

セレクトフィールドに関するイベントを処理するには、以下のイベントハンドラ関数を使用します。

イベントハンドラ関数 引数 イベント
onSelectFieldClick int id,
string text
セレクトフィールドがクリックされ、項目が選択された際に呼び出されます。

引数のidには、イベントが発生したセレクトフィールドのGUIコンポーネントIDが渡されます。 また、引数のtextには、選択された項目名が渡されます。

チェックボックスイベント処理

チェックボックスに関するイベントを処理するには、以下のイベントハンドラ関数を使用します。

イベントハンドラ関数 引数 イベント
onCheckBoxClick int id,
bool state
チェックボックスがクリックされた際に呼び出されます。

引数のidには、イベントが発生したチェックボックスのGUIコンポーネントIDが渡されます。 また、引数のstateには、チェックボックスのON/OFF状態が渡されます。

キーイベント処理

GUIコンポーネント上でキーボードのキーを操作した際には、キーイベントが発生します。

注意:

ただし、キーイベントを利用するには、キーイベントがどのGUIコンポーネント上で発生するかという点に関して注意が必要です。

もし、ウィンドウ上に、テキストフィールドなどのキーボード入力を扱うGUIコンポーネントが配置されている場合、キーイベントは優先的にそれらのGUIコンポーネント上で発生します。もしもその横に、グラフィックスラベルなどを配置していて、その上でキーイベントを拾おうとしても、うまく拾えません。

また、ウィンドウ上にボタンなどの特定のキー操作(ENTERなど)に反応するGUIコンポーネントが配置されている場合にも、その特定のキー操作を、他のGUIコンポーネント上でイベントとして拾えない場合もあります。

そのため、テキストラベルやグラフィックスラベルなどの、一般にキー入力がされないGUIコンポーネント上で、キーイベントを利用したい場合は、 ウィンドウ上にテキスト入力系コンポーネントやボタンなどは配置しない事が推奨されます。

キーイベントを処理するには、以下のイベントハンドラ関数を使用します。

イベントハンドラ関数 引数 イベント
onKeyDown int id,
string key
キーが押された際に呼び出されます。
onKeyDown int id,
int keyCode
キーが押された際に呼び出されます。
onKeyUp iint id,
string key
キーが離された際に呼び出されます。
onKeyUp iint id,
int keyCode
キーが離された際に呼び出されます。

引数は以下の通りです:

上記の通り、2つめの引数には、string 型とint型の2通りがあります。 前者は、キーの表面に印字された(キーラベルの)文字列が格納されます。 例えば「A」のキーを押した際は "A" が、「@」のキーを押した際は "@" が格納されます。 それに対して後者は、キーに1対1で割り振られた整数値が格納され、 例えば「@」のキーを押した際はKEY_ATの値が格納されます。

前者と後者にはそれぞれメリットとデメリットがあります。 前者は比較的手軽に扱える上、 連続したキー入力内容をstring変数末尾に追記していくような処理に便利です。 反面、キー判別に key == "@" といったリテラルの文字列比較を多用するのはミスタイプに弱く、 厳格性に欠けるため、大きなプログラムでは好ましくありません。 それに対して後者は、厳格な記述が可能ですが、 小さなプログラムでは記述が面倒になる場合があります。

文字列 キーコード 文字列 キーコード
A〜Z KEY_A〜KEY_Z 0〜9 KEY_0〜KEY_9
F1〜F12 KEY_F1〜KEY_F12 @ KEY_AT
/ KEY_SLASH
ENTER KEY_ENTER + KEY_PLUS
SPACE KEY_SPACE - KEY_MINUS
TAB KEY_TAB , KEY_COMMA
SHIFT KEY_SHIFT . KEY_PERIOD
CONTROL KEY_CONTROL ALT KEY_ALT
; KEY_SEMICOLON [ KEY_LEFT_SQUARE_BRACKET
^ KEY_CIRCUMFLEX ] KEY_RIGHT_SQUARE_BRACKET
UP KEY_UP DOWN KEY_DOWN
LEFT KEY_LEFT RIGHT KEY_RIGHT

マウスウイベント処理

GUIコンポーネント上でマウスを動かしたり、 クリックしたりすると、マウスイベントが発生します。 マウスイベントを処理するには、以下のイベントハンドラ関数を使用します。

マウス操作は行えるアクションが多彩なので、 それに応じてイベントハンドラも様々なものが用意されています。

イベントハンドラ関数 引数 イベント
onMouseOver int id,
int x,
int y
マウスがコンポーネント領域内に入った際に呼び出されます。
onMouseOut int id,
int x,
int y
マウスがコンポーネント領域外に出た際に呼び出されます。
onMouseMove iint id,
int x,
int y
マウスがコンポーネント領域内で動いた際に呼び出されます。
onMouseCkick int id,
int x,
int y,
int button,
int count
マウスのボタンがクリックされた際に呼び出されます。具体的には、環境に設定された短い時間内で、マウスボタンが「 押し離し 」された場合に呼ばれます。
onMouseDown int id,
int x,
int y,
int button
マウスのボタンが押された際に呼び出されます。
onMouseUp int id,
int x,
int y,
int button
マウスのボタンが離された際に呼び出されます。
onMouseDrag int id,
int x,
int y,
int button
マウスのいずれかのボタンがドラッグされた際に呼び出されます。
onMouseScroll int id,
int degree
マウスホイールが操作された際に呼び出されます。

引数は以下の通りです:

プログラム例

実際に各種イベントハンドラ関数を使用してみましょう。 以下のように記述し、実行してみてください。


import GUI ;
import Graphics ;


// =============================================
// GUIコンポーネントの配置 ここから
// =============================================

// ( x, y ) = ( 300, 20 ) の位置に幅360×高さ480のウィンドウを生成
int windowID = newWindow( 300, 20, 360, 480, "Hello GUI" ) ;

// ( 10, 10 ) の位置に100×50のボタンを配置
int buttonID = newButton ( 10, 10, 100, 50, "PUSH" ) ;
mountComponent( buttonID, windowID ) ;

// ( 10, 70 ) の位置に100×50サイズのテキストフィールドを配置
int textFieldD = newTextField( 10, 70, 100, 30, "INPUT" ) ;
mountComponent( textFieldD, windowID ) ;

// ( 120, 10 ) の位置に200×200サイズのテキストエリアを配置
int textAreaID = newTextArea( 120, 10, 200, 200, "INPUT" ) ;
mountComponent( textAreaID, windowID ) ;

// ( 10, 110 ) の位置に100×20サイズのセレクトフィールドを配置
string text[ 3 ] ;
text[ 0 ] = "TYPE-A";
text[ 1 ] = "TYPE-B";
text[ 2 ] = "TYPE-C";
int selectFieldID = newSelectField( 10, 110, 100, 20, text ) ;
mountComponent( selectFieldID, windowID ) ;

// ( 10, 140 ) の位置に100×20サイズのチェックボックスを作成
int checkBoxID = newCheckBox( 10, 140, 100, 20, "TURBO", true ) ;
mountComponent( checkBoxID, windowID ) ;

// ( 10, 170 ) の位置に100×20サイズのテキストラベルを配置
int textLabelID = newTextLabel( 10, 170, 100, 20, "Hello GUI ! " ) ;
mountComponent( textLabelID, windowID ) ;

// 「Test.png」という名前のPNG形式画像ファイルを読み込み
int graphicsID = newGraphics( "Test.png" ) ;
// ( 10, 220 )の位置に310×200サイズの画像ラベルを配置
int imageLabelID = newImageLabel( 10, 220, 310, 200, graphicsID ) ;
mountComponent( imageLabelID, windowID ) ;

// =============================================
// GUIコンポーネントの配置 ここまで
// =============================================


// =============================================
// イベントハンドラ ここから
// =============================================

// ウィンドウを閉じた際に呼び出される
void onWindowClose( int id ){
	alert( "プログラムを終了します。" ) ;
	exit( );
}

// ボタンクリック時に呼び出される
void onButtonClick( int id, string text ){
	alert( "ボタン " + text + " がクリックされました。" ) ;
}

// セレクトフィールド選択時に呼び出される
void onSelectFieldClick( int id, string text ){
	alert( text + " が選択されました。" ) ;
}

// チェックボックス選択時に呼び出される
void onCheckBoxClick( int id, bool state ){
	alert( "選択状態が " + state + " になりました。" ) ;
}

// マウスドラッグ時に呼び出される
void onMouseDrag( int id, int x, int y, int button ){
	// ドラッグされたコンポーネントの判別
	if( id == imageLabelID ){
		// マウスボタンの判別
		if( button == MOUSE_RIGHT ){
			println( "右ドラッグ X=" + x + " Y=" + y ) ;
		}else if( button == MOUSE_LEFT ){
			println( "左ドラッグ X=" + x + " Y=" + y ) ;
		}
	}
}

// マウスクリック時に呼び出される
void onMouseClick( int id, int x, int y, int button, int count ){
	// クリックされたコンポーネントの判別
	if( id == imageLabelID ){

		// マウスボタンの判別
		if( button == MOUSE_RIGHT ){
			println( "右クリック X=" + x + " Y=" + y ) ;
		}else if( button == MOUSE_LEFT ){
			println( "左クリック X=" + x + " Y=" + y ) ;
		}

		// ダブルクリックの判別
		if( count == MOUSE_DOUBLE ){
			alert( "ダブルクリックされました。" );
		}

	}
}

// キー入力時に呼び出される(キーラベル文字列取得)
void onKeyDown( int id, string key ){
	println( "キー入力 =" + key ) ;
}

// キー入力時に呼び出される(キーコード取得)
void onKeyDown( int id, int keyCode ){
	if( keyCode == KEY_SPACE ){
		alert( "スペースキーが押されました。" ) ;
	}
}

// =============================================
// イベントハンドラ ここまで
// =============================================
EventSample.vcssl

このプログラムを実行すると、ウィンドウが表示され、その上に様々なGUIコンポーネントが表示されます。 各GUIコンポーネントを操作すると、それに応じた処理が実行されます。

実行結果の図。
実行結果
※この画像は模式図です。実際のGUIデザインは、オペレーティングシステムの種類や、VCSSL処理システムのバージョン、その他環境によって異なります。