GO BACK

NewtonScript教室 その4

「簡単なソフトを作ってみよう」



■テキストを使ってアラートを表示する

 では、NewtonScriptの基本も頭に入ったところで、何か作ってみることにしましょう。−−まず、前回作ったプロジェクトを元に、ちょっと修正を加えてみましょう。

 前回作ったプロジェクトのレイアウトは、protoFlatNGoテンプレートをベースに、protoTextButtonテンプレートのボタンを1つ配置しただけ、というとてもシンプルなものでしたね。今回は、これにテキスト入力のフィールドを付け足してみましょう。

 ツールパレットでprotoInputLineアイコンを選び、レイアウトウィンドウのベースとなるビューの上にビューを1つ作成して下さい。このprotoInputLineというテンプレートは、テキストの入力をする時の基本となる部品でしたね。

 次に行なうことは、「それぞれのビューに名前をつける」という作業です。プログラムでビューを利用する場合、ビューに名前がついていないと、どうやって指定すればいいかわからなくなります。そこで、作成してある3つのビューに名前をつけるのです。

 名前の付け方はとても簡単。まず名前を付けたいビューをクリックして選択し、「Browser」メニューから「Template Info」を選びます。すると画面にダイアログが現れるので、ここで「Name」に名前を入力してOKします。

 作成した3つのビューには、それぞれ以下のように名前を付けます。

protoFloatNGo	→	名前: App
protoTextButton	→	名前: ClickMe
protoInputLine	→	名前: InputData

 これで3つのビューはプログラムの中から指定できるようになりました。ここまでできあがると、レイアウトウィンドウは大体こんな感じになります。

 さて、次は、このInputDataのテキストを使って、アラートを画面に表示するようなプログラムをボタンに割り付けるようにしましょう。ClickMeボタンをダブルクリックしてブラウザを開き、先に作成したbuttonClickScriptに書いたプログラムを以下のように書き換えましょう。

func()
begin
	local str := InputData.text;
	str := "Hello, Mr." && str && "!";
	:Notify(kNotifyAlert,"Alert",str);
end

 プログラムの中身は、なんとなくわかりますよね? まあ、とりあえず1行ずつ簡単に説明しておきましょう。


local str := InputData.text;
これは、InputDataというビューのtextアトリビュートを変数strに収めています。

str := "Hello, Mr." && str && "!";
文字列を&&でつなげて、もう一度変数strに収めなおします。

:Notify(kNotifyAlert,"Alert",str);
最後にNotifyを使って変数strを画面に表示します。


 さ、これで全てオッケー。コンパイルしてみましょう。そしてパッケージをNewtonに転送します。ではさっそく実行してみると…? なぜか、エラーがおきてしまいました。これは一体、どういうことでしょう?

 これは、ボタンに割り付けたプログラムでテキストを取り出しているInputDataビューがわからないためにおきたエラーなのです。言い方を変えると、このボタンからInputDataビューが「見えていない」のです。そのため、「そんなビューはないぞ」とエラーが起きてしまったというわけです。



■メッセージの流れを理解する

 なぜ、ボタンからInputDataビューが見えないのでしょうか。それを理解するためには、NewtonScriptでオブジェクトに送られるメッセージがどのような経路を辿っていくかを知る必要があります。

 NewtonScriptでは、プログラム内から他のオブジェクトにメッセージを送った場合、そのメッセージは、画面上のビューの重なり順をそのまま辿って送られていくのです。簡単に図式化すると、こんな感じで流れていると思って下さい。

 わかりますね? 上に重なっているビューから下にあるビューへと、メッセージが送られていくわけです。そして、その経路上でメッセージは送信されるオブジェクトを探していくのです。−−この例の場合、ClickMeから送られたメッセージは、Appに送られ、そしてその後「ルート」と呼ばれるNewtonのシステムが管理しているところへと送られていきます。ということは、もしメッセージの送り先がAppであるならば、Appに送られた時点で「うん、これだ!」とわかり、処理されるわけです。

 今回作ったプログラムで使われている「InputData.text」は、InputDataというビューのアトリビュートを要求するものです。これが実行されると、Newtonはまず実行されたClickMeビューを調べ、そこに要求するものがないと次にAppへと移動してまた調べます。そこでも見つからないと、このアプリケーションを離れ、システムの管理するところへと送られていってしまいます。−−そうです、経路上からは、InputDataビューは「見えない」のです!

 基本的に、上のビューから下にあるビューは見えるのですが、ビューの上に重なっているものは、下のビューからは見えません。この問題を解決するには、InputDataビューを、下にあるAppから「見える」ようにしてやらないといけません。

 レイアウトウィンドウでInputDataビューを選択し、「Templete Info」メニューを選んで下さい。ウィンドウの下に「Declear To」チェックボックスをONにします。すると右側にあるポップアップメニューがアクティブになるので、ここで「App」を選びます(これしか項目は現れませんが)。これで、InputDataはAppから「見える」ようになりました!

 このDeclear Toは、下にあるオブジェクトから自分を見えるようにするものです。これをONにした場合、メッセージはどう流れるのでしょう?−−先ほどと同じように、まずClickMeで「InputData.text」が実行されると、Newtonはそのビュー自身の中からInputDataを探します。そしてないことがわかると、次にAppへと移動してまた探します。すると−−今度は、Appから「InputData」が見えるので、発見したInputData」の中から「text」というアトリビュートを探し出し、無事にその値を返すことができました。

 このように、メッセージがどのように送られていくか、送られる経路上から何が見えて何が見えないのか、それをしっかり理解しておかないと、とんでもない深みにはまることになります。

 では、メッセージの送信の仕組みがちゃんとわかったら、修正したプログラムを再度コンパイルし、Newtonへ転送して動かしてみて下さい。今度はちゃんとボタンは動いたでしょう?



■超簡易電卓を作る!

 今度は、テキストを取り出すだけでなく、結果を画面のビューに書き出すようなものに挑戦してみましょう。また、今の例は文字列を使っていましたから、今度は数字を使った演算をさせる例がいいですね。

 そこで考えたのが、超簡易版の電卓です。普通の電卓は数字のキーを押して計算をしますが、こちらは、直接数式を書き込むと、その答えを計算して書き出す、というようなものにしてみましょう。理由は、たくさんキーを作るのは面倒だからです(笑)。

 これも、先のサンプルプロジェクトのレイアウトを修正して使います。既にAppビューの上にInputDataとClickMeという2つのビューができていますね。これに、答えを表示するビューを1つ新たに付け加えればいいわけです。

 作成するビューは、「protoStaticText」を使います。これはテキストの表示を行なう時に多用するテンプレートですね。このビューを1つApp上に配置し、「Template Info」メニューで名前を「OutputData」と設定して下さい。もちろん、「Declear To」はONにして、「App」から見えるようにします。

 他のビューの位置を多少調整して、上から「InputData」「OutputData」「ClickMe」と縦に並ぶように配置しましょう。

 オブジェクトの位置や大きさなどはだいたいでかまいません。−−レイアウトができあがったら、ClickMeのbuttonClickScriptを以下のように書き換えます。

func()
begin
	local str,fn,num;
	str := InputData.text;
	fn := Compile (str);
	num := Apply(fn,nil);
	str := NumberStr(num);
	SetValue(OutputData,'text,str);
end

 ちょっと今回はややこしそうですねえ。ま、プログラムの中身はひとまず置いて、出来上がったらコンパイルしてNewtonに転送して動かしてみましょう。パッケージを開き、上にあるInputData部分に「1 + 2 * 3」なんて具合に数式を書いて下さい。そしてボタンをクリックすると、その答えが下のOutputDataに書き出されますよ。

 さて、それではプログラムを見てみましょう。今度は新しい命令がいくつもあるので、1行ずつチェックしていきましょう。


local str,fn,num;
これは、変数をひとまとめに宣言している部分です。いくつもの変数を使う時は、このように変数をカンマで区切って続けて書いて宣言することができます。便利な書き方ですね。

str := InputData.text;
まず、先ほどの場合と同じようにInputDataのtextアトリビュートを変数strに収めます。

fn := Compile (str);
これが今回のミソ。この「Compile ()」という関数は、パラメータの文字列をその場でコンパイルして関数オブジェクト(buttonClickScriptのようなプログラムのかたまりのことです)にしてしまうものです。

 ま、ちょっとイメージしにくいでしょうが、要するに「文字列をNewtonが実行できる形に変換し、変数fnに収めている」と考えて下さい。

num := Apply(fn,nil);
このApplyというのは、関数オブジェクトを実行してその結果を得るための関数です。パラメータは2つあり、1つめが実行する関数オブジェクト、2つめはその関数オブジェクトに必要なパラメータとなります。パラメータがいらない時は「nil」というものを設定します。このnilというものは、まあいわば「なんにもない状態」を示すものだと考えて下さい。

 先ほど、Compile()でテキストを関数オブジェクトにしてありますから、これをApplyで実行すれば、その実行結果が返され、変数numに収められるというわけです。

str := NumberStr(num);
これは何をしているのかというと、「数字の値を文字列に変換している」のです。NewtonScriptでは、変数には型はないけれど、値には型があります。ビューのtextアトリビュートというのは、文字列の型の値でないと設定できないのです。ですから、数字をビューに表示する場合は、一度文字列に変換してやらないといけません。

 この「NumberStr()」という関数は、パラメータの数字を文字列に変換して返す働きをします。これで、numの数値が変数strに文字列として収められたわけです。

 これと似たようなものに「StringToNumber ()」というものもあります。こちらは全く反対に、パラメータの文字列を数値に変換する働きをします。2つをセットにして覚えておくとよいでしょう。

SetValue(OutputData,'text,str);
最後に、OutputDataのtextアトリビュートに値を設定して終わりです。ビューのアトリビュートを変更する時は、「SetValue()」という関数を使います。これはパラメータが以下のように3つあります。


SetValue (《ビュー》,《アトリビュート》,《値》)


 こうすると、指定のビューのアトリビュートを指定の値に変更します。−−注意しなければいけないのは、2番目のアトリビュートのパラメータです。これは「text」ではなく「'text」になっていることに気がつきましたか?

 この、始めに’がついているものは「シンボル」と呼ばれるものです。シンボルというのは、文字列や変数などと同様に、プログラムの中で使われる要素の一つです。NewtonScriptでは、ときどきこの「シンボル」という特別な値が使われることがあります。

 これは「Newtonのでオブジェクトやアトリビュートなどを指定するときに使われる特別な呼び名」とでも考えて下さい。Newtonのプログラムでは、そのパッケージやオブジェクト、各種のアトリビュートなどに、この「シンボル」というものが設定されています。

 まあ、シンボルの意味や、なぜそんなややこしいものが存在するかなどは今は知る必要はありません。とりあえず、ここでは「関数の中には、パラメータにシンボルを設定しないといけないものがある」という程度に理解しておいてください。このSetValue()関数の2番目のアトリビュートを指定するパラメータのように、関数で「あるオブジェクトのあるアトリビュート」を指定しなければいけないような場合、シンボルが使われることがあるのです。

 どういう関数でどういうときに使うかは、新たに関数などが登場した時にその都度説明しますから心配はいりません。今は「そういうものがある」とだけ覚えておけば十分でしょう。

◆    ◆    ◆

 今回は、かなり新しい関数などが登場してきて難しかったかも知れません。まあ、Compile()やApply()はちょっと特殊なものなので、覚えなくてもいいでしょう。とりあえずここでは「文字列を数値に、あるいはその逆に変換する方法」「SetValue()でアトリビュートを変更する方法」の2つだけ、しっかりと覚えておいて下さい。この2つは、Newtonのプログラミングをする上で必要不可欠の機能なのです。


GO NEXT


GO HOME