より複雑なスクリプト
次に見るのは、ウィンドウを表示したりデータベースにアクセスしたりといった、先ほどより少しだけ複雑なスクリプトです。ユーザーからの操作を受け付けることが可能になるので、ちょっとしたゲームから特定プログラム向けのシンプルなフロントエンドまで、より高度なアプリケーションを記述することができます。
ウィンドウの表示
他のプログラムを見る前に、シンプルなウィンドウの表示プログラムを見てみましょう。
実は通常のwxWidgetとwxJavaScriptの大きな違いがここにあります。というのも、通常のwxWidgetではアプリケーション自身を表すオブジェクトとして提供されているwxAppがwxJavaScriptでは提供されていないからです。
代わりにwxJavaScriptではwxTheAppというグローバルなオブジェクトが提供され、アプリケーション自身に対する操作はこのオブジェクトを通じて行います。
// シンプルなウィンドウを表示するプログラム
wxTheApp.onInit = function()
{
// 親ウィンドウなし、ウィンドウIDはデフォルトのウィンドウを生成する
var f = new wxFrame(null, -1, "The Simple Window");
// デフォルトではこのウィンドウは表示されないので、表示するように設定する
f.visible = true;
wxTheApp.topWindow = f; // wxTheAppをthisとしても同じ
return true; // Falseを返すと、メインループ終了時にプログラムが終了する
}
カレンダーの表示
続いて、wxWidgetで提供されているカレンダーコントロールを使って、カレンダーを表示するスクリプトを記述してみたいと思います。
この例から分かるように、本家wxWidgetではメソッドとして実装されているものがプロパティとして実装されているなど、本家とは少しだけ勝手が違います。このあたりをカバーするために、wxjsにはHTMLベースのAPIドキュメントが付属していますので、積極的に用いると良いと思います。
// シンプルなカレンダーアプリケーション
// カレンダー日付の枠線指定に使う定数
const wxCAL_BORDER_NONE = 0; // 枠線なし
const wxCAL_BORDER_SQUARE = 1; // 矩形で囲む
const wxCAL_BORDER_ROUND = 2; // 楕円で囲む
wxTheApp.onInit = function()
{
var f = new wxFrame(null, -1, "The Simple Window", wxDefaultPosition, new wxSize(210,210) );
// メインになるカレンダーオブジェクトの生成
var cal = new wxCalendarCtrl( f, -1, new Date());
// カレンダーのヘッダーの色を設定
cal.setHeaderColours(new wxColour(255,255,255), new wxColour(0,0,0) );
// 日付ごとの表示設定を行うオブジェクト
var attr = new wxCalendarDateAttr();
attr.border = wxCAL_BORDER_ROUND; // 枠線の種類は楕円
attr.textColour = new wxColour(255,0,0); // テキスト色は赤
cal.attr[1] = attr; // それを1日に設定
f.visible = true;
this.topWindow = f;
return true;
}
ダイアログボックスとボタン
続いては、ダイアログボックスとボタンを組み合わせたスクリプトを紹介します。
この例では、メインウィンドウ上にあるボタンをクリックするとダイアログが表示され、ダイアログ上のボタンをクリックするとダイアログが閉じるという一連の動作を実現しています。
wxJavaScriptを用いれば、このように柔軟なダイアログボックスの生成や制御を行うことができます。
// ボタンとダイアログのサンプル
wxTheApp.onInit = function()
{
// 親ウィンドウなし、ウィンドウIDはデフォルトのウィンドウを生成する
var f = new wxFrame(null, -1, "The Simple Window", wxDefaultPosition, new wxSize(200, 200) );
// メインウィンドウに表示するパネルを生成。パネルによってコントロールをまとめて管理できる
var pnl = new wxPanel(f, -1);
// パネル上に配置するボタンを生成
var mainbtn = new wxButton(pnl, -1, "ダイアログを表示", new wxPoint(45, 45) );
// 表示するダイアログを生成
var dlg = new wxDialog(f, -1, "サンプルダイアログ", wxDefaultPosition, new wxSize(100, 100) );
// ダイアログ上に配置するボタンを生成
var dlgbtn = new wxButton(dlg, -1, "閉じる");
// メインウィンドウ上のボタンにイベントを設定
mainbtn.onClicked = function(event) {
dlg.showModal(); // モーダルダイアログとして表示
}
// ダイアログ上のボタンにイベントを設定
dlgbtn.onClicked = function(event) {
dlg.endModal(true); // モーダルモードを終了
}
f.visible = true;
this.topWindow = f;
return true;
}
メニューとステータスバーをつける
GUIのツールを作るに当たって、ボタンではなくメニューベースで操作したり、ラベルではなくステータスバーに作業の進捗やアプリケーションの状態を表示したりできるようにすると、何かと便利なことが多いです。
そこで、続いてはメニューとステータスバーを持ったウィンドウを実装したいと思います。
// ウィンドウにメニューとステータスバーを追加する
wxTheApp.onInit = function()
{
// 親ウィンドウなし、ウィンドウIDはデフォルトのウィンドウを生成する
var f = new wxFrame(null, -1, "The Simple Window", wxDefaultPosition, new wxSize(500, 500) );
var menuBar = new wxMenuBar(); // メニューバーオブジェクト
// メニューバーのセット
f.menuBar = menuBar;
f.createStatusBar(4); // 4部屋に分かれたステータスバーを作成
// 最初の二部屋は50ピクセル、残りはデフォルトの大きさにする
f.setStatusWidths( new Array(50, 50, -1, -1) );
// メニューを作る
var menu = new wxMenu();
// バグがあるらしく、ステータスバーに表示する文字列を指定しないと正しく動かない場合がある
menu.append(0, "メニュー1", "ステータスバーに表示する文字列");
menu.actions[0] = function() {
wxMessageBox( "ここにクリックされたときの処理を記述します", "情報", wxICON_INFORMATION );
}
menuBar.append( menu, "メニュー(&M)" ); // メニューバーに登録する
f.visible = true;
this.topWindow = f;
return true;
}
フラクタル図形を描く
wxJavaScriptは、画像にアクセスするための手段も用意されており、GDというモジュールを読み込むことで、画像データの書き出しを行うことができます。
そこで、GDを使った図形描画の実例として、Codezineにある記事を参考に、ドラゴン曲線を描くスクリプトを取り上げたいと思います。
// ドラゴン曲線を描くスクリプト
// 参考資料:http://codezine.jp/article/detail/73
// 利用するモジュールを追加
// 記述するモジュールへのパスは
// このソースファイルから利用したいDLLファイルへの相対パスか、絶対パスを利用する
wxjs.modules.io = new Module("../modules/wxJS_gd.dll");
wxjs.modules.io.load();
// 画像の縦、横のサイズ
const WIDTH = 500;
const HEIGHT = 500;
// 画像の入れ物を用意
var img = new gd.Image( new wxSize( WIDTH, HEIGHT ) );
// 色を確保。背景色を先に用意する。
var white = img.colorAllocate( wxWHITE );
var black = img.colorAllocate( wxBLACK );
// 開始位置
var P = new wxPoint( 170, 140 );
var Q = new wxPoint( 400, 350 );
// ドラゴン曲線を描くための処理
function drawDragon( a, b, n )
{
// 座標計算
var c = new wxPoint();
var xx, yy;
xx = b.x - a.x;
yy = -(b.y - a.y);
c.x = a.x + ( xx + yy ) / 2;
c.y = b.y + ( xx + yy ) / 2;
if( n <= 0 ) {
// ラインを描く
img.line( new wxPoint(a.x, a.y), new wxPoint(c.x, c.y), black );
img.line( new wxPoint(b.x, b.y), new wxPoint(c.x, c.y), black );
} else {
drawDragon( a, c, n-1);
drawDragon( b, c, n-1);
}
}
// ドラゴン曲線を描く。10回繰り返す
drawDragon( P, Q, 10 );
// 描いた画像をファイルに書きだす
var output = new gd.ImageJPEG(img);
output.write(script.root + "/dragon.jpg");
