Smalltalk(VisualWorks with Jun)の基本事項

  1. 導入
  2. ウィンドウを操作
  3. ウィンドウに描画
  4. 問題

1. 導入

Smalltalk(VisualWorks with Jun)の基本事項を習得しましょう。以下に示すプログラムを音読しながら、当該のプログラムをワークスペースへとコピー&ペーストして実行します。この過程を繰り返すことにより、Smalltalkの対話的なプログラミングを垣間見てゆきましょう。


2. ウィンドウを操作

さっそくウィンドウを1つ開いてみます。UI.ApplicationWindownewのメッセージを送り、そのインスタンスを作ります。そして、それを一時変数aWindowに束縛します。その後、それに向かってopenと伝言するだけです。

| aWindow |
aWindow := UI.ApplicationWindow new.
aWindow open

以下のような小さなウィンドウが開いてくるはずです。確認できたら、開いたウィンドウを閉じてください。一仕事、一片付けです。

WindowOperation01

次に、ウィンドウにラベルを付け、ウィンドウの大きさ(最小のサイズ)を指定して開いてみましょう。一時変数aWindowに束縛したUI.ApplicationWindowのインスタンスへlabel:でラベル文字列を伝言し、minimumSize:で幅と高さを伝言します。

| aWindow |
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow open
WindowOperation02

今度は、ウィンドウの背景色を変えてみます。background:のメッセージセレクタを用いて赤色(Graphics.ColorValue red)を指定します。

| aWindow |
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: Graphics.ColorValue red.
aWindow open
WindowOperation03

では、グレースケールで5つのウィンドウを開いてみましょう。(0 to: 1 by: 0.25)の間隔オブジェクトへdo:のメッセージセレクタを用いて繰り返したいブロッククロージャを伝言します。そのブロッククロージャの中では、次々とやってくる0, 0.25, 0.5, 0.75, 1の値を束縛したaValueを使ってグレースケールをこしらえて背景色に設定しています。Graphics.ColorValueへ明度を指定するbrightness:でグレースケールの値aValueを伝言しているところを注視してください。

| aRectangle |
aRectangle := nil.
(0 to: 1 by: 0.25)
    do:
        [:aValue | 
        | aWindow |
        aWindow := UI.ApplicationWindow new.
        aWindow label: '私のウィンドウ'.
        aWindow minimumSize: 400 @ 300.
        aWindow background: (Graphics.ColorValue brightness: aValue).
        aRectangle
            ifNil:
                [aWindow open.
                aRectangle := aWindow displayBox]
            ifNotNil:
                [aRectangle := aRectangle translatedBy: 50 @ 25.
                aWindow openIn: aRectangle]]

ご覧のように5つのウィンドウが右下へとずれながら開いてきます。どのようにしてウィンドウの開く場所をずらしているのかを解説しておきましょう。aRectangleという一時変数に最初nilを束縛しておきます。そして、1つ目のウィンドウが開いた場所(矩形領域)を記憶します。2つ目以降は50 @ 25だけ移動させているのです。

WindowOperation04

次のプログラムはロイヤルブルーの背景色を持つウィンドウを1つ開き、それを斜め下方向へ徐々に移動させます。translatedBy: 2 @ 1というメッセージに注目してください。

| aWindow aRectangle |
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: Graphics.ColorValue royalBlue.
aWindow open.
aRectangle := aWindow displayBox.
100
    timesRepeat:
        [aRectangle := aRectangle translatedBy: 2 @ 1.
        aWindow displayBox: aRectangle.
        aWindow displayPendingInvalidation.
        0.125 seconds wait]

次のプログラムはスプリンググリーンの背景色を持つウィンドウを1つ開き、それを徐々に大きくしてゆきます。 expandedBy: 4 @ 3に着目してください。

| aWindow aRectangle |
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: Graphics.ColorValue springGreen.
aWindow open.
aRectangle := aWindow displayBox.
50
    timesRepeat:
        [aRectangle := aRectangle expandedBy: 4 @ 3.
        aWindow displayBox: aRectangle.
        aWindow displayPendingInvalidation.
        0.125 seconds wait]

3. ウィンドウに描画

では、文字を表示してみましょう。次のプログラムを実行してください。一時変数aStringへ束縛した文字列をウィンドウ内に表示します。文字列から構成テキスト(ComposedText)を作成しています。構成テキストは、文字の大きさなどを指定することのできるオブジェクトです。

| aString aComposedText aWindow |
aString := '私の名前'.
aComposedText := Graphics.ComposedText withText: aString asText
            style: (Graphics.TextAttributes styleNamed: #large).
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: (Graphics.ColorValue brightness: 0.9).
aWindow component: aComposedText.
aWindow open
WindowDrawing01

表示する位置を変えてみます。文字列から作成した構成テキストを表示する際に、displayOn:ではなく、displayOn:at:で場所を指定するようにしました。

| aString aComposedText aVisualBlock aWindow |
aString := '私の名前'.
aComposedText := Graphics.ComposedText withText: aString asText
            style: (Graphics.TextAttributes styleNamed: #large).
aVisualBlock := UI.VisualBlock block: 
                [:graphicsContext :viewBounds |
                | aPoint |
                aPoint := 50 @ 50.
                aComposedText displayOn: graphicsContext at: aPoint].
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: (Graphics.ColorValue brightness: 0.9).
aWindow component: aVisualBlock.
aWindow open
WindowDrawing02

ウィンドウの真ん中に表示するのはどうすればいいでしょうか。displayOn:at:で指定する場所を計算するように変更しています。ビューの大きさと、表示する文字の大きさを考えなくてはいけませんよね・・・。プログラムを読んで確認してください。

| aString aComposedText aVisualBlock aWindow |
aString := '私の名前'.
aComposedText := Graphics.ComposedText withText: aString asText
            style: (Graphics.TextAttributes styleNamed: #large).
aVisualBlock := UI.VisualBlock block: 
                [:graphicsContext :viewBounds |
                | aPoint |
                aPoint := viewBounds center - aComposedText bounds center.
                aComposedText displayOn: graphicsContext at: aPoint].
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: (Graphics.ColorValue brightness: 0.9).
aWindow component: aVisualBlock.
aWindow open
WindowDrawing03

center以外にも、矩形の位置を訊ねるメッセージがあります。配置を覚えておきましょう。

| aCollection aVisualBlock aWindow |
aCollection := Core.OrderedCollection new.
aCollection add: #topLeft -> nil.
aCollection add: #topCenter -> nil.
aCollection add: #topRight -> nil.
aCollection add: #leftCenter -> nil.
aCollection add: #center -> nil.
aCollection add: #rightCenter -> nil.
aCollection add: #bottomLeft -> nil.
aCollection add: #bottomCenter -> nil.
aCollection add: #bottomRight -> nil.
aCollection do: 
        [:anAssociation |
        | aComposedText |
        aComposedText := Graphics.ComposedText
                    withText: anAssociation key asString
                    style: (Graphics.TextAttributes styleNamed: #small).
        anAssociation value: aComposedText].
aVisualBlock := UI.VisualBlock block: 
                [:graphicsContext :viewBounds |
                aCollection do: 
                        [:anAssociation |
                        | aSymbol aComposedText aRectangle aPoint |
                        aSymbol := anAssociation key.
                        aComposedText := anAssociation value.
                        aRectangle := aComposedText bounds.
                        aRectangle := aRectangle align: (aRectangle perform: aSymbol)
                                         with: (viewBounds perform: aSymbol).
                        aPoint := aRectangle origin.
                        aComposedText displayOn: graphicsContext at: aPoint]].
aWindow := UI.ApplicationWindow new.
aWindow label: '私のウィンドウ'.
aWindow minimumSize: 400 @ 300.
aWindow background: (Graphics.ColorValue brightness: 0.9).
aWindow component: aVisualBlock.
aWindow open
WindowDrawing04

4. 問題

私のウィンドウというラベルを持ち、背景色が白色、幅600で高さ200のウィンドウを開き、そのウィンドウの中央に京都産業大学のロゴ画像を描画するプログラムを作成しなさい。

Question01

京都産業大学のロゴ画像は以下のプログラムで取得することができます。

| aLambda anImage |
aLambda :=
        [:urlString |
        | separatorString workDirectory commandLine imageFile imageReader |
        separatorString := Core.String with: OS.Filename separator.
        workDirectory := (OS.SystemUtils getEnvironmentVariable: 'HOME') , separatorString , 'Desktop'.
        commandLine := '(cd ' , workDirectory , ' ; curl -O ' , urlString , ')'.
        OS.ExternalProcess cshOne: commandLine.
        imageFile := workDirectory , separatorString , (OS.URL fromString: urlString) path last.
        imageReader := Graphics.ImageReader fromFile: imageFile.
        imageReader image].
anImage := aLambda value: 'http://www.cc.kyoto-su.ac.jp/~atsushi/images/KyoSanDaiLogo.png'.
^anImage

構成テキスト(ComposedTextのインスタンス)と同様に、画像(Imageのサブクラスのインスタンス)もboundsdisplayOn:at:のメッセージセレクタを用いた伝言に応答することができます。さぁ!がんばって。


Updated: 2019/08/26 (Created: 2008/04/01) KSU AokiHanko