JavaFX を Jython から使ってみる

今日本屋さんにいってJythonの本を見かけた。

おおかた2年前に、すこしさわってたらバグがあって、開発者のウズベッキさんにTwitter から返事をいただいたのが懐かしい。

しばらく触ってないなーというか、Jython って何に使えるんだろーなーとか思いつつ、そういえば、前はSwing とかうごかしてたなー

今なら、JavaFXか。Python スクリプトから、JavaFX 動かせたら便利かしら。

JavaFXも、全然触ってないので、Jython から、JavaFXしてみるかな。

JavaFX SDK のダウンロード

ということで、

JDK 7 update 4 では、JavaFX 2.1 SDK (およびランタイム) が同梱されている。

http://www.oracle.com/technetwork/java/javase/downloads/

JDK 6 で JavaFX 2.1 SDK(およびランタイム) のインストーラ単独で必要な場合、

http://www.oracle.com/technetwork/java/javafx/downloads/

らしい。この間、JDK 7 update 3 入れたところだけど、u4を入れ直す。

インストーラを起動すると、JavaFX のSDK がインストールされる旨、表示される。

javafx_inst01 

JDK のインストールが終わると、JavaFX SDK のインストールが開始

javafx_inst02 

まずは、Java でテスト

プロジェクトのプロパティの、Java Build Path の Libraries タブから、Add External JARs を選択して、JavaFX SDK をインストールしたパスの配下から、jfxrt.jar を選択。

自分の場合は、

C:\Program Files (x86)\Oracle\JavaFX 2.1 SDK\rt\lib\jfxrt.jar

javafx_inst03

チュートリアルに従って、こんちわ JavaFX作成

http://docs.oracle.com/javafx/2/get_started/hello_world.htm

package info.typea.javafx.test;

import javafx.application.Application;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.layout.StackPane;
import javafx.stage.Stage;

public class HelloJavaFx extends Application {
	public static void main(String[] args) {
		launch(args);
	}
	@Override
	public void start(Stage primaryStage) throws Exception {
		primaryStage.setTitle("Hello JavaFX");
		Button btn = new Button();
		btn.setText("Hello");
		btn.setOnAction(new EventHandler() {
			
			@Override
			public void handle(ActionEvent event) {
				System.out.println("Hello JavaFX!");
			}
		});
		
		StackPane root = new StackPane();
		root.getChildren().add(btn);
		primaryStage.setScene(new Scene(root, 300, 250));
		primaryStage.show();
	}
}

当然ながら、こちらは難なく動く。

javafx01

Jython から JavaFXを使う

Jython 自体のインストールは、2年前とほとんど変わっていない。

こちらを参照

あと、Eclipse PyDev プラグイン を利用する。

アップデート サイトは、http://pydev.org/updates/

手順は、こちら

上記手順で、インタプリタに、Python を指定しているところを、Jython のパスを指定し、ライブラリのパスを指定するときに New Jar/Zip(s) から、上記Javaの場合同様、JavaFX の、jfxrt.jar を指定する。

jython_fx_path

後は、何となく、上記Java のコードを移植する。

はまり(注意)点

  • 基底クラスのメソッドを呼ぶ場合、Java と違って、super() を利用する必要がありますよと
  • 無名クラスは、単なる関数に置き換えられますよと
  • Application の launch メソッドに String[] をどうしても渡せなかった。jarray.array(list, java.lang.String)  をあれやこれや試行錯誤したけど、TypeError: launch(): 1st arg can’t be coerced to String[] がでてどうしようもない。String(“”) を渡してお茶を濁しました。
  • Application の launch メソッドには、String[] のみの引数をとるもの(Java の例はこちら)と、Class と String[] をとるものがある。String[] のみの場合、Class を内部で解決しているのだが、Thread.currentThread().getStackTrace() から取得した、StackTraceElement の2つ目を利用している。Javaの場合は、いいのだろうが、Jythonの場合、想定した、Applicationのサブクラスが取得ではなく、sun.reflect.NativeMethodAccessorImpl が取得されている。数時間はまった。うーんこんなコードアリなのかな?Jython側で確認した内容は以下な感じ。
#確認したコード
sts = Thread.currentThread().getStackTrace();
for st in sts:
    print st.getClassName()

#出力
java.lang.Thread
sun.reflect.NativeMethodAccessorImpl
sun.reflect.NativeMethodAccessorImpl
sun.reflect.DelegatingMethodAccessorImpl
java.lang.reflect.Method
org.python.core.PyReflectedFunction
org.python.core.PyReflectedFunction
org.python.core.PyObject
org.python.core.PyObject
org.python.core.PyMethod
org.python.pycode._pyx0
        :

上記を踏まえ、Jython のコード

# -*- coding: utf-8 -*- from javafx.application import Application from javafx.scene.control import Button from javafx.scene.layout import StackPane from javafx.scene import Scene from java.lang import String def btn_click_handler(event): print "hello!" class HelloFx(Application): def main(self): # パラメータにString配列を渡せない!? super(HelloFx, self).launch(self.__class__, String("")) def start(self, primaryStage): primaryStage.setTitle("Hello JavaFX") btn = Button() btn.setText("Hello") btn.setOnAction(btn_click_handler) root = StackPane() root.getChildren().add(btn) primaryStage.setScene(Scene(root, 300, 250)) primaryStage.show() if __name__ == '__main__': h = HelloFx() h.main()

実行してみた

ちゃんと動きつつ、ボタンのクリックで、標準出力もされている。

jython_fx_run

コマンドラインから

  • クラスパスを設定して、実行でOK
  • jython コマンドのパラメータに、クラスパスは指定できなさそう。。。
C:\Users\piroto\workspace372\jython_test>set CLASSPATH="C:\Program Files (x86)\O
racle\JavaFX 2.1 SDK\rt\lib\jfxrt.jar"

C:\Users\piroto\workspace372\jython_test>jython hello_fx.py
Device "Intel(R) HD Graphics" (\\.\DISPLAY1) initialization failed :
WARNING: bad driver version detected, device disabled. Please update your driver
 to at least version 8.15.10.2302
hello!

そんな感じ。

Follow me!

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です