*&color(red){JavaFX Script プログラミング} [[原文>https://openjfx.dev.java.net/JavaFX_Programming_Language.html]] Last Updated 11 June 2007 JavaFX Script™ (JavaFX)は宣言型言語であり、静的な型を扱うプログラミング言語です。 そのため、JavaFXには、ファーストクラスファンクション、宣言型の構文、リスト内包表記、増分評価などがあります。 JavaFXはJava2D、Swingを使い、簡単にGUIを作成できます。 このドキュメントではJavaFXプログラミングの非公式(暫定的)な説明を行います。 *&color(blue){コンテンツ:} ---- // おまじない // これをかいておくだけでページ内リンクが勝手につくられていく #contents(fromhere) #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *&color(blue){基本型} ---- JavaFXでは4つの基本型を定義しています。 -String -Boolean -Number -Integer Javaの型との対応を以下に示します。 |&font(u,b){JavaFX} | &font(u,b){Java}| |String |java.lang.String| |Boolean |java.lang.Boolean| |Number |java.lang.Number| |Integer |byte,short,int,long,BigInteger| Example: var s = "Hello"; s.toUpperCase(); // yields "HELLO"; s.substring(1); // yields "ello"; var n = 1.5; n.intValue(); // yields 1 (1.5).intValue(); // yields 1 s.substring(n); // yields "ello" var b = true; b instanceof Boolean; // yields true 型変換は、引数の受け渡しの際に自動的に数値型に対して行われるか、 もしくは値をJavaメソッドに(へ)返します。 さらに、Number型をInteger型に変換する時は暗黙的キャスト(変換)が行われます。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *&color(blue){Javaオブジェクトの呼び出し} ---- JavaFXは以下の事が可能です。 -Javaクラスのインポート -Javaオブジェクトの作成 -メソッド呼び出し -インタフェースの実装 例にその一例を示します。 import javax.swing.JFrame; import javax.swing.JButton; import java.awt.event.ActionListener; import java.lang.System; var frame = new JFrame(); var button = new JButton("押してね"); frame.getContentPane().add(button); button.addActionListener(new ActionListener() { operation actionPerformed(event) { System.out.println("押しましたね"); } }); frame.pack(); frame.setVisible(true); 次のような画面が表れます。 &ref(http://www34.atwiki.jp/javafx/pub/frame.png) ただし上記は、JavaFXで推奨するコードではありません。 JavaFXでの記述方法は以下です。 Frame { content: Button { text: "押してね" action: operation() { System.out.println("押しましたね"); } } visible: true } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *変数 ---- 変数を定義するキーワードは以下です。 -var JavaFXではインタプリタが型を推測するので、型の宣言は必須ではありません。 以下に抽象例を示します。 var 変数名 : 型名[?,+,*] = 初期値 次に、変数につけることのできるオペレータの基本的な意味を以下に示します。 |記号|意味| |?|任意(nullも可)| |+|1以上| |*|0以上| 以下に例を示します。 var nums:Number* = [1,2,3]; 上記の例では&font(b){nums}という&font(b){Number}型のインスタンスを持つ変数が宣言されています。 &font(b){nums}は0以上の値で成り立つため、初期値は[1,2,3]を与えています。 &font(b,i){:typename, [?,+,*], =initializer}の部分は任意です。 そのため、以下の記述方法も同様の意味を示します。 var nums = [1,2,3]; #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *ファンクション, 配列, 式, 演算子 ---- ファンクションはJavaFXの機能的な部分のみを記述します。 ファンクションの定義には以下のキーワードを用います。 -function function内には以下が記述できます。 -変数の宣言 -return文 また、条件文、ループ文、try/catch文などを含む宣言や定義を行います。(オペレーションを参照) ファンクションには命令を記述しません。 以下に簡単な例を以下に示します function z(a,b) { var x = a + b; var y = a - b; return sq(x) / sq (y); } function sq(n) {return n * n;} function main() { return z(5, 10); } 型の宣言は強制的ではありありませんが、静的な型です。(詳細は以下で述べる) 一般にデータの構造体は配列を使います。 括弧("[ ]")で囲み、コンマで区切ります。 var week_days = ["Mon","Tue","Wed","Thur","Fri"]; var days = [week_days, ["Sat","Sun"]]; 配列はオブジェクトの連続として表されます。 一方、JavaFXでは配列自体はオブジェクトではなく、ネストもしません。 上例でネストされた配列(days)は自動的に以下のように修正されます。 days == ["Mon","Tue","Wed","Thur","Fri","Sat","Sun"]; // returns true 配列サイズの取得は以下のキーワードを用います。 -sizeof 以下に例を示します。 var n = sizeof days; // n = 7 配列の要素の計算などに用いられる簡略表記を以下に示します。 -".." 以下の例では階乗の関数を定義し、1から100までの奇数の合計をresultとしています。 function fac(n) {return product([1..n]);} var result = sum([1,3..100]); 配列の要素の型は全て同じです。 配列はJavaでは以下のように記述します。 var wednesday = days[2]; JavaFXでは、"[ ]"は式選択(express selection)としても使います。 この場合、[]の内部の式はboolean式です。 この式は、[]の内部の条件を満たす要素を持つ配列を返します。 XPathのように、[]記号を内部に含んでいるとわかると、コンテキストオブジェクトはドット記号にアクセスします。 var nums = [1,2,3,4]; var numsGreaterThanTwo = nums[. > 2]; // yields [3, 4] かわりに、変数はコンテキストオブジェクトを宣言する方法もあります。 例えば、以下は同様の結果です。 numsGreaterThanTwo = nums[n|n > 2]; 配列要素の順番を返すオペレータを以下に示します。(XPathのposition()ファンクションと同様) -indexof carとcdrのリストを式選択で使用する方法を以下の例に示します。 function car(list) {return list[indexof . == 0];} function cdr(list) {return list[indexof . > 0];} carは簡単に以下のようにも記述できます。 function car(list) {return list[0];} 例 var list = [1..10]; car(list); // yields 1 cdr(list); // yields [2,3,4,5,6,7,8,9,10] 空の配列とnullは一致します。 [] == null // yields true sizeof null // yields 0 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *可変長配列 ---- 演算子(=)の割り当てに加えて、データ変更の演算子を以下に示します。 -insert -delete この文法や記号の書式は、XQuery-Updateの仕様と同様です。 **Insert文 insert文は次のフォームのいずれかで表されます。 insert Expression1 [as first | as last] into Expression2 insert Expression1 before Expression2 insert Expression1 after Expression2 insert文は示されたExpression1の評価をし、返された項目をその後ろの位置に挿入します。 ***into Exception2には属性か変数が入ります。 Expression2の参照する属性が1つならば、insertと同様の結果になります。 as firstを記述すると、Expression2によって示されたリストの先頭に挿入されます。 as lastを記述すると、Expression2によって示されたリストの末尾に挿入されます。 どちらも記述されない場合はas lastがデフォルトとなります。 例 var x = [1,2,3]; insert 12 into x; // yields [1,2,3,12] insert 10 as first into x; // yields [10,1,2,3,12] insert [99,100] as last into x; // yields [10,1,2,3,12,99,100] ***before,after Expression2は属性か変数の選択記述(selection expression)です。 beforeを記述すると、挿入位置は選択要素の前になります。 afterを記述すると、挿入位置は選択要素の後になります。 例 var x = [1,2,3]; insert 10 after x[. == 10]; // yields [1,2,3,10] insert 12 before x[1]; // yields [1,12,2,3,10] insert 13 after x[. == 2]; // yields [1, 12, 2, 13, 3, 10]; #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **Delete文 ---- Delete文は以下いずれかの書式で記述されます。 delete variable delete Expression.attribute delete variable[predicate] delete Expression.attribute[predicate] 最初の2つの書式は、全ての変数、属性を削除します。 削除後は、[]またはnullに割り当てられます。 最後の2つの書式は、評価が一致した要素のみ削除します。 例 var x = [1,2,3]; insert 10 into x; // yields [1,2,3,10] insert 12 before x[1]; // yields [1,12,2,3,10] delete x[. == 12]; // yields [1,2,3,10] delete x[. >= 3]; // yields [1,2] insert 5 after x[. == 1]; // yields [1,5,2]; insert 13 as first into x; // yields [13, 1, 5, 2]; delete x; // yields [] #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *クエリ配列(部分的未完成) ---- JavFXはMirandaやHaskellのような関数型言語のリスト内包表記をサポートしています。 ただし、Javaプログラマが理解しやすい文法になっています。 JavaFXでは以下のリスト内包表記があります。 -select -foreach 以下に例を示します。 class Album { attribute title: String; attribute artist: String; attribute tracks: String*; } var albums = [Album { title: "A Hard Day's Night" artist: "The Beatles" tracks: ["A Hard Day's Night", "I Should Have Known Better", "If I Fell", "I'm Happy Just To Dance With You", "And I Love Her", "Tell Me Why", "Can't Buy Me Love", "Any Time At All", "I'll Cry Instead", "Things We Said Today", "When I Get Home", "You Can't Do That"] }, Album { title: "Circle Of Love" artist: "Steve Miller Band" tracks: ["Heart Like A Wheel", "Get On Home", "Baby Wanna Dance", "Circle Of Love", "Macho City"] }]; // Get the track numbers of the albums' title tracks // using the select operator: var titleTracks = select indexof track + 1 from album in albums, track in album.tracks where track == album.title; // yields [1,4] // the same expressed using the foreach operator: titleTracks = foreach (album in albums, track in album.tracks where track == album.title) indexof track + 1; // also yields [1,4] //再考箇所 リスト内包表現は1つ以上の入力、任意のフィルタ、ジェネレータ式から成り立ちます。 それぞれのソースリストは変数に関連しています。 リスト内包表現で得られるリストは、フィルタを満たすソースリストの要素の直積(両者に存在するすべてのデータのすべての組み合わせ)の部分集合にジェネレータを適用したものです。 //再考箇所 リスト内包表現には繰り返しのための簡単な記述があります。 以下にその例を示します。 select n*n from n in [1..100] このリストは1から100の全ての数の二乗の命令を含むリストです。 ただし、"n"は上式のローカル変数です。 The use of a filter is shown by the following definition of a function which takes a number and returns a list of all its factors, //未完成 function factors(n) { return select i from i in [1..n/2] where n % i == 0; } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *式(未完成) ---- JavaFXで使用する事の出来る演算子を以下に示します。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *String文字列, Stringによる表示 ---- Stringリテラルには2つの記述方法があります。 -シングルクオーテーションで囲む方法 -ダブルクォーテーションで囲む方法 以下にその例を示します。 var s = 'Hello'; var s = "Hello"; 後者では「{ }」を使うことで、文中に変数を挿入できます。 var name = 'Joe'; var s = "Hello {name}"; // s = 'Hello Joe' 挿入文の中に文字列を挿入する例を以下に示します。 var answer = true; var s = "The answer is {if answer then "Yes" else "No"}"; // s = 'The answer is Yes' Javaと違う部分は、文字列に改行が含まれる点です。 var s = "This contains new lines"; #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *引用識別子 ---- 「<< >>」で囲まれたキャラクタ(空白を含む)の全てが識別子として扱われます。 クラス名、変数名、ファンクション、属性名を別のものとして使う事ができます。 例 var <<while>> = 100; この方法により、JavaとJavaFXとで同じ名前のキーワードが使用できます。 import javax.swing.JTextArea; var textArea = new JTextArea(); textArea.<<insert>>("Hello", 0); #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *範囲式 ---- 等差数列を扱う配列の定義は次の書式で定義されます。 [number1..number2] この式はnumber1からnumber2までの整数を要素にもつ配列を定義します。 例 var nums = [0..3]; System.out.println(nums == [0,1,2,3]); // prints true デフォルトで公差(値の間隔)は1です。 デフォルト以外の公差を設定したい場合は、number1の後ろをコンマで区切り次の値を記述します。 例えば、1-10までの奇数をもつ配列は以下のように定義します。 [1,3..10] number1がnumber2より大きいと降順になる。 var nums = [3..0]; System.out.println(nums == [3,2,1,0]); // prints true #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *String,Number,Dateフォーマット ---- Stringの書式化は以下の構文で記述します。 expr format as directive format asオペレータがサポートする形式(directive)を以下に示します。 -java.text.DecimalFormat -java.text.SimpleDateFormat -java.util.Formatter directiveが%で始まっていればjava.util.Formatterが使われます。 exprの型がNumber型ならば、java.text.DecimalFormatterが使われます。 exprの型がjava.util.Date型ならばjava.text.SimpleDateが使われます。 directiveオペランドは式ではなく、識別子です。 これで、directiveの表現がコンパイル時に正しいか静的なチェックします。 例 import java.util.Date; 100.896 format as <<%f>>; // yields '100.896000' 31.intValue() format as <<%02X>>; // yields '1F' var d = new Date(); d format as <<yyyy-MM-dd'T'HH:mm:ss.SSSZ>>; // yields '2005-10-31T08:04:31.323-0800' 0.00123 format as <<00.###E0>>; // yields '12.3E-4' #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *オペレーション プログラムの処理は以下のキーワードで定義します。 -operation 以下にその例を示します。 import java.lang.StringIndexOutOfBoundsException; operation substring(s:String, n:Number): String { try { return s.substring(n); } catch (e:StringIndexOutOfBoundsException) { throw "sorry, index out of bounds"; } } 上記の例は、2つの引数をもつsubstringが定義されています。 sはString型、nはNumber型であり、戻り値はString型です。 上述した、assignment文, delete文, insert文に加えて、次以降に示す文はoperation内に定義します。 **Expression(式)文 文でよく使われる例を以下に示します。 例 System.out.println("Hello World!"); #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **if文 if文はJavaと同じです。 ただし、「{ }」の省略はできません。 例 if (condition1) { System.out.println("Condition 1"); } else if (condition2) { System.out.println("Condition2"); } else { System.out.println("not Condition 1 or Condition 2"); } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **while文 if文はJavaと同じです。 ただし、「{ }」の省略はできません。 例 var i = 0; while (i < 10) { if (i > 5) { break; } System.out.println("i = {i}"); i += 1; } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **try文 try文はJavaと同じです。 java.lang.Throwableを拡張するものだけでなく、全てオブジェクトのスローをキャッチできます。 例 try { throw "Hello"; } catch (s:String) { System.out.println("caught a String: {s}"); } catch (any) { System.out.println("caught something not a String: {any}"); } finally { System.out.println("finally..."); } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **for文 for文はforeach文と同じ書式です。 この場合、文中のリスト内包表記で生成された各要素で実行されます。 例 for (i in [0..10]) { System.out.println("i = {i}"); } // print only the even numbers using a filter for (i in [0..10] where i % 2 == 0) { System.out.println("i = {i}"); } // print only the odd numbers using a range expression for (i in [1,3..10]) { System.out.println("i = {i}"); } // print the cartesian product for (i in [0..10], j in [0..10]) { System.out.println(i); System.out.println(j); } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **return文 return文はJavaと同じです。 例 operation add(x, y) { return x + y; } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **throw文 throw文はJavaと同じです。 ただし、java.lang.Throwableだけでなく全てのオブジェクトをスローします。 例 import java.lang.Exception; operation foo() { throw new Exception("this is a java exception"); } operation bar() { throw "just a string"; } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **break文,continue文 break文とcontinue文はJavaと同じです。 Javaと同様にwhile文,for文内で使用してください。 しかし、ラベルはサポートしていません。 例 operation foo() { for (i in [0..10]) { if (i > 5) { break; } if (i % 2 == 0) { continue; } System.out.println(i); } } operation bar() { var i = 0; while (i < 10) { if (i > 5) { break; } if (i % 2 == 0) { continue; } System.out.println(i); i += 1; } } #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **do文 do文はAWT Event Dispatch Threadが処理を続けている間に、JavaFXコードのバックグラウンドスレッドを実行できます。 これにより、UIがハングアップしてしまうのを防ぎます。 現在この実行には、バックグラウンドスレッドの実行している間、イベントを送出するためにjava.awt.EventQueueが使用することで実装されます。 通常、全てのJavaFXコードはAWT Event Dispatch Threadで実行します。 do文の中に記述されたコードのみ他のスレッドで実行されます。 このようなコードはJavaオブジェクトにアクセスするだけでかまいません。 (そのオブジェクトは必要に応じて、自身のスレッドと同期処理をしなければなりません。) 例 import java.net.URL; import java.lang.StringBuffer; import java.lang.System; import java.io.InputStreamReader; import java.io.BufferedReader; // in the AWT EDT var result = new StringBuffer(); do { // now in a background thread var url = new URL("http://www.foo.com/abc.xml"); var is = url.openStream(); var reader = new BufferedReader(new InputStreamReader(is)); var line; while (true) { line = reader.readLine(); if (line == null) { break; } result.append(line); result.append("\n"); } } // now back in the EDT System.out.println("result = {result}"); 上例で、緑の部分はEDT(Event Dispatch Thread)で実行され、do文の中に記述された赤いコードにブロックされるように見えます。 しかし、event dispatch loopは、バックグラウンドスレッドの完了を待っている間に新しくスタック上に作られます。 このため、do文が実行している間、GUIイベントは実行を続けます。 しかし、複数のevent dispatch loopがスタックを増やす事ができ、極端な場合、stack overflow exceptionを引き起こしてしまうので、この方法は完全な解決策ではありません。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} ***do later文 ---- do文は2つ目の書式は、バックグラウンドスレッドを同期実行をするとは逆に、EDT内部の非同期実行を行います。 (java.awt.EventQueueinvokeLaterの機能が与える方法) 以下に例を示します。 import java.lang.System; var saying1 = "Hello World!"; var saying2 = "Goodbye Cruel World!"; do later { System.out.println(saying1); } System.out.println(saying2); このコードは次の出力をします Goodbye Cruel World! Hello World! #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *クラスとオブジェクト ---- クラスの記述方法を以下に示す -classキーワード -クラス名 -任意でextendsキーワードを記述(継承元のクラス名はコンマで区切る) -「{」 -属性、ファンクション、オペレーションのリストを記述(文末にセミコロンを記述) -「}」 例 class Person { attribute name: String; attribute parent: Person inverse Person.children; attribute children: Person* inverse Person.parent; function getFamilyIncome(): Number; function getNumberOfChildren(): Number; operation marry(spouse: Person); } 属性の宣言を以下に示す -attributeキーワード -属性名 -「:」 -属性の型 -基数詳述(cardinality specification)(「?」は任意の値、「*」は0以上,「+」は1以上) -inverse節を任意でつけられる。(inverse:属性の型のクラスで他の属性と双方向の関係を指定する) -「;」 attribute AttributeName : AttributeType Cardinality inverse ClassName.InverseAttributeName; inverse節が存在し属性の値が変更されると、JavaFXインタプリタは自動的にinverse属性をアップデートします。 アップデートの種類、属性の基数によって挿入、削除、置換をします。 複数の値を持つ属性(*や+の基数詳述が記述されているもの)は配列を表します。 「[ ]」オペレータ経由でアクセスされ、insertやdeleteオペレータと同時にアップデートされます。 Javaのメソッドとは違い、JavaFXのすべてのメンバオペレーション、メンバファンクションの内容は、クラス宣言の外に定義されます。 以下に例を示します。 function Person.getNumberOfChildren() { return sizeof this.children; } パラメータと返す型はクラス宣言内でオペレーションとファンクションの宣言は必要です。 しかし、定義の省略は可能です。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **属性の宣言 ---- 属性に値を与えて宣言する事ができます。 初期値は、生成されたオブジェクトのコンテキストでのクラス宣言で記述された属性の命令で評価されます。 //再考 import java.lang.System; class X { attribute a: Number; attribute b: Number; } attribute X.a = 10; attribute X.b = -1; var x = new X(); System.out.println(x.a); // prints 10 System.out.println(x.b); // prints -1 bindオペレータを用いた増分評価も宣言可能です。 import java.lang.System; class X { attribute a: Number; attribute b: Number; attribute c: Number; } attribute X.a = 10; attribute X.b = bind a + 10; attribute X.c = bind lazy b + 10; var x = new X(); System.out.println(x.a); // prints 10 System.out.println(x.b); // prints 20 System.out.println(x.c); // prints 30 x.a = 5; System.out.println(x.a); // prints 5 System.out.println(x.b); // prints 15 System.out.println(x.c); // prints 25 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **オブジェクトリテラル ---- オブジェクトは、属性の初期値のリストを区切った中括弧に続くクラスの名前から成立する構文の宣言を割り当てる。 //再考 それぞれの初期値は以下で記述されます。 -属性名 -「:」 -式 -定義する値 ただし、増分評価については以下を参照して下さい。 以下に例を示します。 var chris = Person { name: "Chris" children: [Person { name: "Dee" }, Person { name: "Candice" }] }; Javaオブジェクも割り当て構文(allocation syntax)をサポートしています。 Javaクラスでは、Javaのコンストラクタのように引数を渡す事ができます。 import java.util.Date; import java.lang.System; var date1 = new Date(95, 4, 23); // call a java constructor var date2 = Date { // create the same date as an object literal month: 4 date: 23 year: 95 }; System.out.println(date1 == date2); // prints true オブジェクトリテラルの中にローカル変数を宣言する事も可能です。 ローカル変数はオブジェクトリテラル自信のスコープの中のみで利用できます。 In addition, a variable referring to the object being initialized may be declared by using the var keyword as a pseudo-attribute. //さらに、オブジェクトを 擬似属性としてvarキーワードを使用すると宣言された初期値参照する変数。 //再考 例 var chris = Person { var: me name: "Chris" var child1 = Person { name: "Dee" parent: me } var child2 = Person { name: "Candice" } children: [child1, child2] }; #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} *アップデートトリガ ---- JavFXにおいて、classにはコンストラクタがありません。 また、JavaBeansプロパティのような"setter"もありません。 その代わりとなるキーワードを以下に示します。 -trigger これは、SQLのような数値の変更イベントを扱うキーワードです。 トリガには、ヘッダとその内部を記述します。 ヘッダには、利用するトリガイベントの型を記述します。 トリガの内部とは、イベントが発生した時に実行する処理です。 トリガの内部では、オペレーションで利用できる文が全て利用できます。 また、トリガもメンバファンクションやオペレーションのような動きをします。 コンテキストオブジェクトにはthisキーワードを通してアクセスします。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **トリガの作成 ---- オブジェクトの作成をtriggerにした例を以下に示します。 import java.lang.System; class X { attribute nums: Number*; } trigger on new X { insert [3,4] into this.nums; } var x = new X(); System.out.println(x.nums == [3,4]); // prints true この例では、Xクラスがインスタンス化されると実行されるよう定義しています。 ここでは、初期値をnums代入します。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **insertトリガ ---- insertをトリガに用いて、複数の属性を指定した例を以下に示します。 import java.lang.System; class X { attribute nums: Number*; } trigger on insert num into X.nums { System.out.println("just inserted {num} into X.nums at position {indexof num}"); } var x = new X(); insert 12 into x.nums; // prints just inserted 12 into X.nums at position 0 insert 13 into x.nums; // prints just inserted 13 into X.nums at position 1 上例で"num"は挿入する要素の変数名です。(変数名は任意です。) 正しい挿入位置を示しています。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **deleteトリガ ---- deleteをトリガに用いて、複数の属性を指定した例を以下に示します。 import java.lang.System; class X { attribute nums: Number*; } trigger on delete num from X.nums { System.out.println("just deleted {num} from X.nums at position {indexof num}"); } var x = X { nums: [12, 13] }; delete x.nums[1]; // prints just deleted 13 from X.nums at position 1 delete x.nums[0]; // prints just deleted 12 from X.nums at position 0 上例で"num"は削除される要素の変数名です。(変数名は任意です。) 正しい削除位置と要素を示しています。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} **replaceトリガ ---- 置換をトリガに用いて、1つまたは複数のの属性を指定した例を以下に示します。 import java.lang.System; class X { attribute nums: Number*; attribute num: Number?; } trigger on X.nums[oldValue] = newValue { System.out.println("just replaced {oldValue} with {newValue} at position {indexof newValue} in X.nums"); } trigger on X.num[oldValue] = newValue { System.out.println("X.num: just replaced {oldValue} with {newValue}"); } var x = X { nums: [12, 13] num: 100 }; x.nums[1] = 5; // prints just replaced 13 with 5 at position 1 in X.nums x.num = 3; // prints X.num: just replaced 100 with 3 x.num = null; // prints X.num: just replaced 3 with null 上例の"oldValue"と"newValue"は置換元と置換先の要素の変数です。 正しい置換要素と位置を示しています。 #right(){[[top>http://www34.atwiki.jp/javafx/pages/25.html#]]} ---- &trackback()