vieweditattachhistorytopchangessearchhelp

第64回


■SqueakではじめるSmalltalk入門   第64回


本連載では、名前は知っていてもなかなか触れる機会のないSmalltalkについて、最近話題のSqueakシステムを使って紹介しています。

前回は、システムウインドウに対して普段、なにげなく行なっているGUI操作が、内部的にはそのまま、オブジェクトとしてのウインドウ(SystemWindowのインスタンス)へのメッセージ送信で実現されており、当然のことながら、同様のことをSmalltalkコードとしても記述可能であることを体験していただきました。次のステップとして、このシステムウインドウを使った簡単なアプリケーションを作ってみたいと思います。

お題はGUIビルダです。…と申しましても、Interface Builderのような、あんな立派なものをここで作るのは無理なので、動作モデルをとてもシンプルなものにいたします。

イメージとしては、組み込むべきGUIウィジェットを(もちろんSqueakシステムには、OS XのAquaほど多彩で洗練されたものはないのですが、それでもいくつかある候補から…)選択して、ダミーのウインドウにドロー系ツールの要領で矩形を描くと、それが指定した矩形範囲に設置される…というのでいかがでしょうか。できあがったGUIウィジェットを含んだウインドウは、それと同じものを作るためのSmalltalkコードとしてはき出す機能を持つことも想定します。

作業に取りかかる前に、まずは、ウォーミングアップと復習を兼ねて、ドロー系ツールライクに矩形を描く操作などのマウス操作より、必要な情報を抜き取る方法を、いつもどおり脱線ぎみにおさらいしてみましょう。

マウスの操作から情報を取り出す方法にはいくつかありますが、よく使われるメソッド名は #fromUser です。いわゆるユーティリティメソッドで、レシーバとして指定されたクラスに属するインスタンスを返してきます。このとき、直前のマウス操作から情報を抜き出して、インスタンスのプロパティにそれを反映させます。

たとえば、クリックした場所の座標を得るには、

Point formUser


を print it (cmd + P) します。Pointは、端的には座標オブジェクトの属するクラスです。

print it操作の直後、マウスカーソルは十字(クロスヘア)になり、クリック操作が行なわれるまで、他の操作を受け付けなくなります。クリックすると同時に、マウスポインタのホットスポットの位置の座標(Pointのインスタンス)が返されます。ちなみに、Point class >> #fromUser の定義は、こんなふうになっています。

Point class >> fromUser
  Sensor waitNoButton.     "ボタンが押されていたら放すまで待つ "
  Cursor crossHair show.   "マウスカーソルをクロスヘアに       "
  Sensor waitButton.       "ボタンが押されるのを待つ           "
  Cursor normal show.      "マウスカーソルを通常の矢印に       "
  ^ Sensor cursorPoint     "現在のポインタの位置を返す         "


そのまんまですね。Sensor cursorPoint は、この連載の最初の頃に取り上げた、簡易ペイントツールでも登場しているイディオムで、評価すると(クリックを待たずに)ただちにマウスカーソルのホットスポットの位置を返してきます。なお、このメソッド「Point class >> #fromUser」は、クラス Pointではなく、クラス Point の属するクラス(メタクラス)の Point class に定義されていることに注意してください。

今回、システムウインドウ内へGUIウィジェットを設置するために必要な矩形情報も、同様にして得ることができます。今度は、Point の代わりに、Rectangle、つまり矩形クラスに同じメッセージ「fromUser」を送ることで、Rectangle class >> #fromUser という別のメソッドを起動します。

Rectangle fromUser


この式の print it の直後、右下に開いたカギ型のポインタに変わるので、適当な場所で、ドローツールで矩形を描く要領でマウスをドラッグ操作します。ドラッグを終えてマウスボタンから指を離すと同時に、それまで描いた矩形領域の左上と右下からなる、矩形オブジェクト(a Rectangle)が返されます。

余談ですが、このとき起動される Rectangle class >> #fromUser の定義は、このようになっています。

fromUser
  ^ self fromUser: 1 @ 1


これは、マウスの動きを強制するグリッドを設けず(言い換えれば、最小単位の1×1ピクセルによる強制を指示して)#formUser: を起動しすることを意味します。念のため、#fromUserと#formUser: は別のメソッドなので注意してください。Java風に、同名メソッドのオーバーロード(多重定義)と考えてもよいのですが、それよりはもっと単純に、メソッド名にはコロンまでが含まれる…(当然、その有無で区別されるべき)と考えたほうが、より現実に即しています。

グリッドでの強制がどんなものかは、次の式のように、パラメータに1 @ 1以外を与え print it すれば、すぐ分かります。

Rectangle fromUser: 16 @ 16


Rectangle class >> #formUser: の定義は、Point class >> #fromUser とは違い、ちょっと複雑ですが、これまでの知識でも読み解けなくもないと思います。もし、興味があればチャレンジしてみてください。「fromUser:」の部分を選択して browse it (cmd + B)でブラウザを呼び出し、上のリストから、Rectangle class fromUser: {instance creation}の項目をクリックすれば見ることができます。

ここで、矩形オブジェクトといっても、あくまで抽象的なもので、描いた矩形やそこに含まれる画像が切り取られるわけではないことに注意してください。やはり復習なのですが、画像を切り取るには、画像オブジェクトを定義したクラス Form に、同じ formUser を送信します。

Form fromUser


a Rectangle を得るときと同様の操作で、それが終わると、a Form が返されます。どんなものが切り取られたか見てみたいときは、こんなふうにして、帰ってきた a Form にさらに自身を画面左上に表示するよう指示することで可能です。

Form formUser displayAt: 0 @ 0


ここで早速、Point fromUser を使ってみるのも面白いでしょう。

Form fromUser displayAt: Point fromUser


最初のドラッグで選択した矩形から切り取った画像を、二度目のクリックの場所に表示します。なお、遊んで汚してしまった画面は、デスクトップメニューの「ディスプレイを再表示 (r)」できれいにできます。なお、この種の遊びをするときには、はじめからコードに再描画を折り込んでおくという手もあります。

Display restoreAfter: [Form fromUser displayAt: Point fromUser]


切り取った画像をモーフにしてしまうのも、またひとつの方法です。

Form fromUser asMorph openInHand


このコードでは、切り取った画像は、ただちに同等の表示内容のモーフに変換され、マウスでピックアップした状態になります。スケッチモーフに変換すれば、ペイントツールを使った編集も可能です。

| sketch |
sketch := SketchMorph withForm: Form fromUser.
sketch center: Display center.
sketch openInWorld.
sketch editDrawing


fromUserについては、Color fromUser や、StrikeFont fromUser も面白いと思います。是非、print itして、遊んでみてください。

このページを編集 (6123 bytes)


Congratulations! 以下の 1 ページから参照されています。

This page has been visited 966 times.