FXD の問題

本家の blog で書いたプレゼンツール Caraibe を JavaFX 1.2 に対応させた時の例外の続きです。

もう一度、例外について書いておくと、Caraibe を JavaFX 1.2 に対応させたら、以下のような例外が発生したというものです。

WARNING * WARNING * WARNING * WARNING * WARNING
An attempt has been made to add node to a new group without
first removing it from its current group. See the class
documentation for javafx.scene.Node for further information.
This request will be granted temporarily but it will
be refused in the future. Please change your code now.
node=Group [id=rectangle] oldgroup=Group newgroup=Group
Stack trace follows.
java.lang.IllegalArgumentException
        at javafx.scene.Group$_SBECL.onChange(Group.fx:162)

Group クラスに後から Node を追加したらダメというように読めます。しかし、後から追加する部分を排除しても、この例外は出続けてしまいます。

うーん、こまった。

と嘆いていたら、ヒョンなところから問題が解決しました。

なんと、Group クラスとは全然関係ないところが問題だったのです。

問題はなんと FXD 関連のクラス、つまり Illustrator/Photoshop の Plug-in で生成した FXZ/FXD ファイルの読み込みに関する部分だったのです。

FXZ ファイルの読み込みにはトップレベルのノードを読み込む方法と、名前づけられたノードを読み込む方法があります。

問題は後者の名前づけられたノードを読み込む方です。名前づけられたノードを読み込んで、表示するだけの簡単なスクリプトを以下に示します。

var content: FXDContent = FXDLoader.loadContent("{__DIR__}resources/rectangle.fxz");
var node = content.getNode("rectangle");

Stage {
    title : "FXD Sample"
    scene: Scene {
        width: 200
        height: 200
        content: [ node ]
    }
}

このコードを実行すると、出るのですよ例外が。はぁ? って感じでしょ。

このスクリプトを以下のように変更すると、例外は出ません。

var content: FXDContent = FXDLoader.loadContent("{__DIR__}resources/rectangle.fxz");
var node = content.getRoot();

// もしくはこんなコード
// var node: Node = FXDLoader.load("{__DIR__}resources/rectangle.fxz");

// あるいはこんなコード
// var node: FXDNode = FXDNode { url: "{__DIR__}resources/rectangle.fxz" };

Stage {
    title : "FXD Sample"
    scene: Scene {
        width: 200
        height: 200
        content: [ node ]
    }
}

ようするにルートノードは大丈夫なわけです。

ここで、いろいろと試してみようと思って、次のようなスクリプトを実行させたわけです。

var content: FXDContent = FXDLoader.loadContent("{__DIR__}resources/rectangle.fxz");
var node = content.getNode("rectangle");

単にノードを読み込むだけのスクリプトです。

ところが、ところが、これを実行すると、ウィンドウが表示されるのです。

はぁ????????

意味が分かりません。

でも、なんとなく原因が分かりました。このコードだけでもウィンドウが表示されてしまうということはどこかで Stage と Scene を作って、node を表示させているわけです。

一度表示したノードを違うところでもう一度表示することはできません。なので、こんな警告が出ているのでしょう。

原因が分かったら、対処は簡単。ノードの複製を作ればいいのです。したがって、最初のスクリプトは次のように書けば大丈夫。

var content: FXDContent = FXDLoader.loadContent("{__DIR__}resources/rectangle.fxz");
var node = Duplicator.duplicate(content.getNode("rectangle"));

Stage {
    title : "FXD Sample"
    scene: Scene {
        width: 200
        height: 200
        content: [ node ]
    }
}

しかしなぁ...

これは明らかにバグですよね。

今は英語を書く時間がないので、JIRA (バグデータベース) に登録できないのですが、名古屋の講演が終わったら、登録しようと思います。