2014年 12月

SwingNode と TextFlow

JavaFX

このエントリーは、JavaFX Advent Calendar 2014, 11日目のおまけです。

昨日は @toruwest さんの「JavaFXのTreeViewでアニメーションしてみる」でした。

明日は @skrb さんの「Java Advent Calendarと一緒になにか書きます」です。

今年も JavaFX でいろいろなことを楽しんだのでそのうちの一部を紹介します。

はじめに、Swing では JTextPane ってのがあって普通の JTextArea よりも柔軟に扱えます。

テキストのスタイルを簡単に変更できたりしてとても便利でした。

JavaFX に JTextPane に相当するものがあるかと言えば無さそうです。

編集できなくて表示だけなら TextFlow がかなり強力に使えます。

私は TextFlow を使うのを躊躇ってなんとか JTextPane を JavaFX で使ってやろうと SwingNode に手を出してしまいました。

何をしたかったかというとテキスト検索で検索文字にヒットしたらその文字を良く解るように色づけ、太字表示をしたかっただけです。

SwingNode は javafx.embed.swing.SwingNode クラスでこれを使うには

public void setContent(JComponent content)

で Swing コンポーネントをセットします。

ただし、JavaFX アプリケーションスレッドを使わずに

public static void invokeLater(Runnable doRun) メソッドを使用して

doRun.run()を、AWTイベント・ディスパッチ・スレッドで非同期的に実行させます。

このメソッドは実際は java.awt.EventQueue.invokeLater()を呼び出しているだけです。

Swing コンポーネントの操作をするときには面倒だけど AWT のスレッドでってことのようです。

はっきり言ってよっぽどの事情がないかぎり SwingNode なんて使おうと思わない。(^_^;)

いつも通り雑なサンプルプログラムを載せておきます。

プログラムの実行結果は次のようになります。

1

2

3

4

 

いちおう動くけど見栄えが良いものではありませんね。

ちなみに私は疑り深い人間なので試しに AWT のスレッドを使わなければ本当に駄目?なのか試してみました。

コンパイルは通りました。

実行時エラーでも出るのかなと思いきや何も起こりませんでした。

このような小さなプログラムでははっきりした不具合が出ないようです。

裏を返せば非常に危険だということになるのかな?

もう一つ気がかりなことは時々プログラムの起動時に黒くなってしまうことがあります。

やっぱり何か無理があるのかもしれない。(単なるバグだと思う。)

そんなこんなでせっかく JavaFX でプログラム組むんだから古い Swing なんて面倒な思いしてまで使いたくないよね!

そこで TextFlow を使ってみることにしました。

TextFlow は JTextPane と違って編集ができません。

ただ表示するだけです。

使い方も至って簡単です。

javafx.scene.text.Text クラスのインスタンスを生成しそれにテキスト及び書式を設定します。

その Text オブジェクトを TextFlow インスタンス生成時のコンストラクタの引数として渡してあげればいいだけです。

もしくは textFlow.getChildren().add(text); として TextFlow インスタンスに加えることもできます。

簡単に使えてスタイルの自由度も JtextPane より遙かに高いので使い道はあるかと思います。

Text のスタイルは public final void setStyle(String value) を使って設定します。

引数はインライン CSS を与えるだけのお手軽仕様です。

TextFlow を使ったサンプルプログラムも載せておきます。

このプログラムの実行結果は次のようになります。

5

2

7

8

 

やっぱ JavaFX オンリーでつくったプログラムのほうが見栄えがいいですね!

それにしても JavaFX っておもしろいね!

この二つのサンプルプログラムでは JavaFX Night で櫻庭さんが例を挙げていたようなことをこの二つのプログラムでやっています。

TextField と TextArea に文字が入力されてなければトグルボタンを非活性化にし、文字が入力されたら活性化させることを Bind を使って実装してみました。

       search.disableProperty()
                .bind(
                        Bindings.when(textArea.textProperty().isEmpty().or(textField.textProperty().isEmpty()))
                        .then(true)
                        .otherwise(false));

Java らしくない気がしないでもないですが便利です。

あっ、つまり検索してから TextArea か TextField をどちらかのテキストを空にしてしまったら Clear できないってことになるな。

まっ、いいか。

トグルボタン使っちゃったからなぁ・・・

ただのサンプルなのでそこらへんは見逃してくださいまし!(>_<。)

JavaFX 楽しい!

Hatena タグ:

新しい記事 »