[[FrontPage]]

#contents

2014/03/21からのアクセス回数 &counter;

* Pnuts連携機能の紹介 [#ud6b6681]
Artisocとjavaで作られたクラスの橋渡しをするために、javaで作られたスクリプト言語pnutsを使用します。
Pnuts連携機能を使うことで、Artisocのモデルの変数の値を読み込んだり、変更することが可能となり、
ArtisocのモデルにjavaのGUIを利用した画面を追加することも可能になります。

Artisocでpnutsスクリプト機能を利用するには、Artisocプロフェッショナルバージョンが必要です。

** ArtisocのPnuts連携用組み込み関数 [#m3643beb]
pnutsと連携するためにArtisocに以下の2つの組み込み関数が用意されています。
- ExecPnuts: puntsで記述されたスクリプトを実行します。
- EvalPnuts: pnutsの式を評価し、その値を返します。

これらの使い分けとしては、pnutsで関数を定義し、Artisocで使えるようにExcecPnutsでスクリプトファイルを実行するのに、
ExcecPnutsを利用し、pnutsの関数呼び出しにEvalPnutsを利用すると便利です。

** ExecPnutsの最も簡単な例 [#j718fa5e]
ExecPnutsの動きを確認するために、最も簡単なモデル(&ref(p01.model);)とpnutsスクリプト(&ref(p01.pnuts);)を使って、
どの動作をみてみます。

Artisocのモデルは、Universeの直下に変数vがあるだけで、Universeのステップの開始Univ_Step_Beginでpuntsスクリプトを実行し、
Universeのステップの終わりUniv_Step_Endで変数vの値をプリントするという簡単なものです。

p01.pnutsのスクリプトは、Universe.vの値を取得し、その値に1を足した値を新たにUniverse.vにセットする
簡単なものです。printlnの出力は、Artisocの画面にはでませんが、ArtisocのLinux版では端末の画面に出力されます。

pnutsからArtisocの変数の値を取得する場合には、PnutsUtil::getValue関数を使い、
値をセットする場合には、PnutsUtil::setValue関数を使用します。

#pre{{
v = PnutsUtil::getValue(engine, "Universe.v")
println(v)
PnutsUtil::setValue(engine, "Universe.v", v + 1)
}}

実行するとUniverse.vの値が1ずつ増えていることが確認できます。

&ref(th_p01.jpg);


** JavaのGUIを追加する例 [#u4ec8fce]
先の例では、変数vの値を1ずつ増やす簡単なものでしたが、JavaのGUIを使ってユーザがモデルの外から
値を設定する例を次に示します。((Artisocのコントロールパネルの代わりにjavaのGUIを使う感じです))

モデルには、&ref(p02.model);を使用し、pnutsスクリプトには&ref(p02.pnuts);を使用します。

モデルの変更点は、Univ_Initでp02.pnutsのスクリプトを実行している部分だけです。
これを実行すると、以下のようなJava Swingのフレームが表示され、テキストフィールドに値をセットすると、
Artisocのコンソール画面に表示される値が変更されます。

&ref(p02.png);



p02.pnutsのスクリプトをみてみましょう。説明のために行番号を付けています。


- 1-2行:import文で必要なjavaのパッケージをインポートし、pnutsから使えるようにします
- 4-9行:SwingのJFrame, JLabel, JTextFieldを使ってGUIを作っています
- 10-18行:pnutsの便利な機能で、PnutsLayoutを使って画面のレイアウトをセットします
- 19-20行:作成したフレームを表示します
- 23-28行:変更ボタンを押されたときのコールバック関数を定義します。ここではUniverse.vにテキストフィールドの値をセットしています。
- 30行:Pnutsの便利な機能でGUI部品のイベントとコールバック関数をbind関数を使って結合します。
- 32行:フレームをルートフレームにセットします。

#pre{{
    1     import("pnuts.awt.*")
    2     import("javax.swing.*")
    3    
    4     f = JFrame("pnuts test")
    5     l = JLabel("Univser.v")
    6     tf = JTextField(10)
    7     tf.setText("")
    8     b = JButton("変更")
    9     b.setToolTipText("This is a JButton");
   10     layout(f,
   11          [PnutsLayout, "cols=1,padx=10,pady=5",
   12               [PnutsLayout, "cols=2,padx=2",
   13                    l, tf
   14               ],
   15               b
   16          ]
   17     )
   18     //f.setSize(200, 200)
   19     f.pack()
   20     f.show()
   21    
   22     /**** 変更ボタンを押されたときのコールバック関数 ****/
   23     function do_b_update()
   24     {
   25          v = tf.getText()
   26          println(v)
   27          PnutsUtil::setValue(engine, "Universe.v", v)
   28     }
   29    
   30     bind(b, "actionPerformed", function(e) do_b_update())
   31    
   32     JOptionPane::setRootFrame(f)    
}}


このようにpnuts連携機能を使うとArtisocでjavaのGUI機能を使った独自のモデルを構築することができます。

** シミュレーションの終了時の処理 [#nf4b1750]
先の例で、ArtisocにPnutsを使って別の処理を追加する場合、シミュレーションのエラー(PLAY_ERRORMSG)
やシミュレーションの終了(PLAY_STOPPED)のタイミングが必要になります。

このような場合、pnutsのbind関数を使ってArtisocのengineからPLAY_ERRORMSG, PLAY_STOPPED等のイベントを取得し、
それに対するコールバック関数で処理することができます。

p02.pnutsにシミュレーションの終了時にGUIを閉じる処理を追加してみましょう。32行目の前に以下の処理を追加します。

#pre{{
function do_close(e) 
{
     id = e.getID()
     if (id == MASActionEvent::PLAY_ERRORMSG ||
         id == MASActionEvent::PLAY_STOPPED) {
     f.dispose()
     }
}

bind(engine, "actionPerformed", do_close)

}}

シミュレーションの終了ボタンを押すとjavaで作ったGUIが連動して閉じます。

*** Pnuts連携時の注意点 [#r228a912]
pnutsで記述したスクリプトは、Artisocの外部で別のスレッドとして動いているため、
Artisocの実行環境設定で、実行ウェイトとして、1ミリ以上の値をセットしてください。

&ref(Simulation_Setting.png);



** 配列を扱う [#q979ae78]
pnutsからArtisocの配列を参照する時には、PnutsUtil::getArray関数を使用し、セットするときにはPnuts::setArray関数を使用します。


例としては、&ref(p04.model);と&ref(p04.pnuts);を使用します。
この例題では、sia, sba, sda, ssaの配列の値をdia, dba, dda, dsaの配列にコピーしています。

配列変数の値を取得するには、getValueと同様にengineとモデルのパス(以下ではUniverse.sia)を指定します。
#pre{{
sia = PnutsUtil::getArray(engine, "Universe.sia")
}}

配列の値をセットする場合には、pnutsで[]内に値をカンマ区切りでセットすると配列が作成されます。
以下のようにsa変数にHello, Mr., Takemotoとセットすると、Universe.dsaにその値がセットされます。
#pre{{
sa = ["Hello", "Mr.", "Takemoto"]
PnutsUtil::setArray(engine, "Universe.dsa", sa)

}}

** エージェントの生成 [#va04ab9c]
pnutsからArtisocのエージェントを生成することができます。

エージェント生成の例として、アリの例題を作成してみます。
初期設定でランダムな方向に直進するアリエージェントをJavaで生成したボタンを押して
生成してみます。

モデルには、&ref(p_ant.model);を使用し、スクリプトには、&ref(p_ant.pnuts);を使用します。

&ref(p_ant.png);



p_ant.pnutsのSpawn Antボタンのコールバック関数を以下の様に定義します。
PnutsUtil::CreateAgt関数の引数は、engineと生成するエージェントのパスです。


#pre{{
function do_b_update()
{
     PnutsUtil::CreateAgt(engine, "Universe.ground.ant")
}
}}

** Pnutsスクリプトのデバッグ [#sd3a5fbe]
pnutsには、デバッガが組み込まれており、Pnutsスクリプト内からデバッガを起動することができます。

p_ant.pnutsの代わりにdebug.pnutsを起動します。(&ref(p_debug.model;参照)
#pre{{
Univ_Init{
     ExecPnuts("debug.pnuts")
}
}}

&ref(debug.pnuts); の内容は、以下の様にします。loadFileの中にデバッグするスクリプトをセットします。

#pre{{
import("pnuts.tools.VisualDebugger")

function debug()
{
     loadFile(modelDir + "/p_ant.pnuts", VisualDebugger().createContext(getContext()))
}

fork(debug)
}}

これを実行すると、以下の様なデバッガ画面が現れます。マウスで右クリックするとブレークポイントをセット
することができますが、以下の様にコールバックにブレークポイントをセットするとフリーズしてしまいます。
(要検討)

しかし、Pnutsスクリプトの処理の流れや、変数の設定値をチェックしながらデバッグするにはとても助かります。


&ref(debug_win.png);




** コメント [#p46ea21d]
#vote(おもしろかった,そうでもない,わかりずらい)

皆様のご意見、ご希望をお待ちしております。
#comment_kcaptcha

トップ   新規 一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
SmartDoc