何某日和

「カメラ」のち「ハンダゴテ」ところにより「プログラミング」 ── そんな私“かめきち”のウェブサイト

2012.10.24:減法混色

概要

 GUIシリーズ第4弾の「減法混色」。先週の「加法混色」と似ていますが、今回は「モデル1つに対して複数のビューが対応」しているアプリケーションを構築します。 ちなみにテキストはこちら(http://www.cc.kyoto-su.ac.jp/~atsushi/Programs/ColorCMY/index-j.html

準備

マシンメンテナンス

 息をするように...とは言いませんが、マシンメンテナンスを行いましょう。(日々のマシンメンテナンス

今日の目標

 まずは目標物をご覧に入れましょう。

完成したアプリケーション(背景色:シアン) 完成したアプリケーション(背景色:マゼンタ) 完成したアプリケーション(背景色:イエロー)

先週のRGBに引き続き、今週拵えるのはCMY(Cyan、Magenta、Yellow:色材の三原色)の強さをスピンボタンで調整することで、色を作り出すアプリケーションです。

準備プログラムの実行

 以下のプログラムを実行して、準備を整えましょう。

| aCollection |
(aCollection := OrderedCollection new)
    add: #url: -> 'http://www.cc.kyoto-su.ac.jp/~atsushi/Programs/ColorCMY/ColorCMY.st';
    add: #comment: -> 'Copyright 2008-2011 KSU (Kyoto Sangyo University). All Right Reserved.';
    add: #bundle: -> #KSU;
    add: #package: -> 'KSU-Template';
    add: #nameSpace: -> #KSU;
    add: #category: -> 'KSU-Template';
    add: #class: -> #{KSU.ColorCMY};
    add: #protocol: -> #examples;
    add: #selector: -> #example1;
    add: #execute: -> [#{KSU.ColorCMY} value example1];
    yourself.
JunSystem
    perform: ((aCollection collect: [:each | each key]) inject: String new
            into: [:selector :key | selector , key]) asSymbol
    withArguments: (aCollection collect: [:each | each value]) asArray
準備完了

今回のGUI部品:Label, Spin Button, Percent Done Bar

  • GUI部品の設置(ラベル、スピンボタン、プログレスバー)
  • ちゃんと動きますか?

GUI部品の設置(ラベル、スピンボタン、プログレスバー)

 次の画像を参考にGUI部品を貼り付けてゆきましょう。

Palette Window

今回は、ラベル(Label)、スピンボタン(Spin Button)、プログレスバー(Percent Done Bar)を貼り付けます。

MainWindow cyanLabel magentaLabel yellowLabel cyanGauge Basics cyanGauge Details cyanGauge Color magentaGauge Basics magentaGauge Details magentaGauge Color yellowGauge Basics yellowGauge Details yellowGauge Color cyanPercent magentaPercent yellowPercent

最後にインストールを忘れずに。

ちゃんと動きますか?

Do it 完成したウィンドウ

いかがでしょう、アプリケーションとして正しく動くでしょうか。

コードリーディング

  • color
  • cyanGauge, magentaGauge, yellowGauge
  • updateColor, postOpenWith:
  • updateColorCyan:, updateColorMagenta:, updateColorYellow:
  • 先週との違い

color

 先週にも同じ構造を見ましたよね。では、このプログラムを説明してみてください。

regGauge, greenGauge, blueGauge

 先週にも同じ構造を見ましたよね。では、このプログラムを...(同

updateColor, postOpenWith:

 先週にも同じ構造を見ましたよね。では...(同

updateColorCyan:, updateColorMagenta:, updateColorYellow:

 (同

先週との違い

 ことごとく先週と似通った構造のようですが、違う点もあります。実はここが結構重要なのです。

先週は「フィールド」と「スライダー」が登場し、それぞれ別々のモデル(ValueHolder)を持っていました。 ところが、今週の「スピンボタン」と「プログレスバー」は、実は1つのモデルを共有しているのです。

では、今回のモデルはどのような仕事を受け持っているのでしょうか。値が変わった際に、何をするのでしょうか。調べてみましょう。 どんな仕事を頼まれたのかは、ValueHolder自身が知っていますから、ValueHolderに尋ねてみましょう。(ここではcyanGaugeのValueHolderを調べます。)

Inspect it ColorCMYをインスペクト cyanGaugeをインスペクト

example1をインスペクト(Inspect)したら、cyanGaugeにダイブ(Dive)します。さらにdependentsにダイブすると、以下のように3つの項目が表示されるはずです。

1つ目の依存物 2つ目の依存物 3つ目の依存物
  1. BlockValue with: TheUnassignedValue
  2. a MacOSXComboBoxInputFieldView
  3. a MaxOSXProgressWidgetView

(※実行環境により結果は異なります。)

 どうやら3つの仕事を受け持っているようです。1つ目の仕事は、cyanGaugeメソッドの中で依頼した「色変更の仕事」です。 2つ目は「InputFieldView」とあるので、スピンボタンに付随するテキストフィールドを指していて、 3つ目は「ProgressWidgetView」とあるので、プログレスバーを指しているのでしょう。 それぞれ、値が変更された時に「色を変更する」「欄内の数値を変更する」「進行度の割合を増減する」といった仕事が行われるのです。

 2つ目と3つ目は、どちらもビューです。1つのモデル(cyanGauge)が同時に複数のビューに情報を提供しているのです。 「MVC」と一言に言えば、モデルとビューとコントローラが、それぞれ1つずつ連携している様子を思い浮かべるかもしれませんが、 決してそうではなく、ビューやコントローラさえも、1つのモデルに対して複数対応していて良いのです。

 何かしらの出来事(情報、モデル)があれば、それに対して幾つものマスメディア(ビューたち)が取り上げるではありませんか。 MVCという構造は現実世界に存在する構造であって、特別なものでも難しいことでもないのです。さて、これで少しは「MVC」に親近感が湧いたでしょうか。

コードライティング

 今日も今日とてプログラミング。今回は、ちょっとしたTipsの紹介を兼ねてプログラミングを行いましょう。

「検査」メニューの設置

 ちょうど前節で、example1をインスペクトする機会がありました。最初からオブジェクトと対話したいのなら「Inspect it」すると思いますが、 「Do it」した後から「あぁ、Inspect itしておけばよかった」...なんて思うことは多々あります。 その際に便利なのが「検査」メニュー。メニューバーに「検査」という項目を入れて、選択すればインスペクタが開くのです。便利ですよ。

 詳細は説明しませんが、ヒントとして画像を掲載しておきます。おきばりやしとくれやす!

  • メニューに「検査」項目を増やす(Value:には何を書くべき?)
メニュー「検査」の追加 「検査」メニューを選択する インスペクタが開いた

余談

ObjectMemory allObjects

 Smalltalk上で生きている全てのオブジェクトに会えるということを知っていますか。以下をインスペクトすれば、全てのオブジェクトをつかまえることができます。

ObjectMemory allObjects
ObjectMemory allObjectsで全てのオブジェクトを見てみる

前節で「インスペクトし忘れた」などということが起きても問題ありません。この全オブジェクトの一覧があれば、そこから探し出せば良いのです。 例えば、ColorCMYのexample1を動かしておいて、全オブジェクトのリストからColorCMYクラスのオブジェクトだけを探し出します。

ObjectMemory allObjects select: [:anObject | anObject class = KSU.ColorCMY]
ColorCMYクラスのオブジェクトを全て捕まえた メッセージを送ったら、確かに値が変化した

すると、見事にオブジェクトが見つかりました。試しに、シアンの値を「0.1」にするようメッセージを投げてみたところ、確かにシアンの値が変更されて、背景色が赤っぽくなりました。

こんなことができるということは、今、動いている「トランスクリプト」も「ワークスペース」も「ブラウザ」も、ひっつかまえてメッセージを送ることができるのです。 なんて自由な世界!!(その分、非常に危ないのですが。。。)

とても断片的ですが、以上が余談でした。

さいごに

 さて、先週と似たようなテーマでしたが、いかがでしたか。 コードリーディングをほとんど割愛してしまいましたが、それほど先週と似たプログラムだったのです。 さて、そのプログラムを見て、共通の構造を見出だせたでしょうか。そして、それを括り出せるでしょうか...。 再来週の「リファクタリング」が楽しみですね!(

保存を忘れずに

 今日取り組んだ内容を保存しておいて、また来年に活かしてくださいね。