2015
JavaFX
JDK8u40 で追加された Spinner と Dialog を試してみた。
JDK8u40 で追加された Spinner と Dialog を試してみた。 とりあえず回避方法をみつけた。
このエントリーは上記の続きです。
と言っても大したことはやっていません。
ただ、新しく追加されたこれらの情報が見つからないので適当にグリグリした記録です。(^_^;)
今回は、Formatted Text を Spinner に適用してみました。
前回までは Spinner に表示されるテキストは左よりになっていて違和感のかたまりがありました。
これを右よりにします。
そして、Spinner に入力される値によりテキストのスタイルも変更してみます。
私はどうしたらいいのか解らなかったのでリファクタリングを使い、Spinner クラスの TextField を下記のように設定していました。
|
Field field = spinner.getClass().getDeclaredField("textField"); field.setAccessible(true); tf = (TextField) field.get(spinner); tf.setStyle("-fx-text-fill: black; -fx-font: 14pt 'serif'; -fx-alignment: CENTER_RIGHT;"); |
これでも動いたのですが spinner.getEditor() で TextField にアクセスできることが後で発覚しました。((((;゜Д゜)))))))
public final TextField getEditor()
Gets the value of the property editor.
Property description:The editor used by the Spinner control.
API ドキュメントはちゃんと見なければいけませんね。(^_^;)
これで Font 関係は設定できます。
次に Formatted Text を使ってみます。
これも全然情報が見当たらない。
○racle さん、早く新しいチュートリアルをだしてください!
今回は日本円の書式設定を試しました。
CurrencyStringConverter を使えばいいようです。
他にも IntegerStringConverter や ShortStringConverter やら Converter がたくさんあります。
今イチ使い方が良く解らないので適当に手探りでやってみました。
本当は、TextFormatter<Number>とspinner.valueProperty()のバインドさせたかったのですが何やら例外吐くので無理にバインドしないことにしました。(ヲヒ
とりあえず下記コードで目的は果たしました。
コードは部分的なものですが残りは今までとほぼ変わりはないので省略します。
全て見たい方は冒頭の関連エントリーのリンクを辿ってくだしませ。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62
|
@Override public void initialize(URL url, ResourceBundle rb) { spinner.setEditable(true); // 書式設定 CurrencyStringConverter currencyStringConverter = new CurrencyStringConverter(); TextFormatter<Number> formatter = new TextFormatter<>(currencyStringConverter); // // 動くけど例外吐くからダメ (>_<。) // formatter.valueProperty().bindBidirectional((Property)spinner.valueProperty()); // スピナーに書式設定 spinner.getEditor().setTextFormatter(formatter); // バインド例外吐くから・・・ formatter.setValue(INITAL_VALUE); // アプリケーション起動時のスタイル spinner.getEditor().setStyle("-fx-text-fill: black; -fx-font: 14pt 'serif'; -fx-alignment: CENTER_RIGHT;"); // Spinner のデザインを変更 spinner.getStyleClass().add(Spinner.STYLE_CLASS_SPLIT_ARROWS_VERTICAL); spinner.valueProperty().addListener((ov, oldValue, newValue) -> { // バインド例外吐くから・・・ formatter.setValue(newValue); // RT-40257 https://javafx-jira.kenai.com/browse/RT-40257 if (beh == null) { beh = (SpinnerBehavior) ((SpinnerSkin) (spinner.getSkin())).getBehavior(); spinner.focusedProperty().addListener((obs, b, b1) -> { if (b && !b1) { beh.stopSpinning(); } }); } // スピナーのスタイルを変更する if (newValue <= 30_000) { spinner.getEditor().setStyle("-fx-text-fill: red; -fx-font: italic bold 14pt 'serif'; -fx-alignment: CENTER_RIGHT;"); }else{ if (newValue >= 70_000) { spinner.getEditor().setStyle("-fx-text-fill: blue; -fx-font: italic bold 14pt 'serif'; -fx-alignment: CENTER_RIGHT;"); }else{ spinner.getEditor().setStyle("-fx-text-fill: black; -fx-font: 14pt 'serif'; -fx-alignment: CENTER_RIGHT;"); } } if (newValue <= 30_000 && poor.getValue()) { poor.setValue(Boolean.FALSE); showPoorDialog(); } if (newValue >= 70_000 && rich.getValue()) { rich.setValue(Boolean.FALSE); showRichDialog(); } }); } |
プログラムを起動します。
右寄りでフォントスタイルも設定通りになってます。
Formatted Text もちゃんと機能しています。
日本円のシンボルマークの \ も表示され、三桁ごとに , も表示されています。

Spinner の下向きの矢印ボタンを押して値を減らします。
30,000円以下になると Spinner の文字が赤色になり、イタリックで太文字に変更されます。
円のシンボルマークはイタリック、太字にはならない仕様のようですね。
Dialog も出すようにしているのは今まで通りです。

最小値( 0 )はこのように表示されます。

上向きの矢印ボタンを押して Spinner の値を増やしていきます。
70,000円以上になると Spinner の文字が青色になり、イタリックで太文字に変更されます。
Dialog も出すようにしているのは今まで通りです。

最大値までしか増えません。

今回は Spinner の設定を編集可能としているので 500 を入力してみました。
ちゃんとテキストフォーマットが効いてます。

上向きの矢印ボタンを押して値を増加させてみます。
編集した値に追加設定値が足されていくようです。

実に良く出来ています。
しかし、ちょっと挙動がおかしなところがあります。
例えば、9999999999 と入力したら最大値を表示する場合と
Exception in thread “JavaFX Application Thread” java.lang.NumberFormatException: For input string: “9999999999”
という例外を吐く場合があります。
実際に数字以外を入力させても上記例外が発生します。
ここらへんの対応のセオリーとかそのうち出てくるだろうから今は気にしないでおこう。(ヲヒ
JavaFX 面白いからもっともっと情報があるといいのにね!
TAGS: JavaFX |
2015年3月26日8:57 PM |
Computer General
私の人生で初めてラジオを購入しました。
これまでラジオはもらい物ばかりでわざわざ購入するようなものでは無かった。
若い人は知らないと思うけどラジカセというのがあってラジオ単体の製品を購入する人はわたしの周りではいなかった。
私の叔父は株をやっていてよく短波放送を聞くのにラジオをいつも携帯していた。
ラジオ単体で購入するには金額的もしくは携帯性、使用目的を限定する場合だと思う。
そんなこんなで何故今時ラジオなの?
ラジオなんてインターネットでも放送しているコンテンツもあるし、ストリーミングでラジオだけでなくテレビ放送もしている時代なのに。
私が気まぐれで買ってしまった SONY ICZ-R250TV は予約録音ができる!
昔のラジオにそんな機能はありませんでした。
内蔵メモリーも 8GB もあり、さらに SD カードも使える。
私は 32GB の SD カードを追加しました。
これで録音可能時間を当分気にすることはないだろう。
予約機能も設定が豊富で、日時指定(1回のみ)、曜日設定、毎日の指定も可能です。
至れり尽くせりです。
予約件数は 20 件までとなっていますが十分でしょう。
気になるラジオの基本的な性能はどうかというと感度良好です。
これは地域や使用環境によって大きく変わるのであくまで私の個人的な使用環境でのことですのでご注意を。
今まで私の家にあったラジオ(ラジカセを含む)の中では一番感度良好です。
と言っても随分昔の機種なので技術の進歩で当然の結果だと思います。
また、受信状況が良くない場合のためにループアンテナも付属しています。
ノイズ対策もノイズキャンセル機能を搭載しているのでお好みで設定できます。
SONY ICZ-R250TV は AM 放送の他に FM、ワンセグ TV 放送も受信できます。
ちなみにFM補完放送にも対応しています。
ロッドアンテナとホイップアンテナも装備しています。
私の使用環境ではFM、ワンセグ TV 放送の受信は厳しいチャンネルもありました。
これは外部アンテナを使用すれば問題ないと思いますがワンセグ TV 放送は興味ないのでいいです。
FM 放送は滅多に聞かないと思うし、たまに車の運転中に聞くチャンネルはうれしいことに感度良好で綺麗に聞くことができたので Good! でした。
ラジオの基本性能でもう一つ特筆することがあります。
音が良い!
あくまでラジオとしてですが音が良い!
これは音響機器メーカーとしての Sony のこだわりでしょうか。
専用スピーカーBOXとバスレフ方式を採用しているので低音が心地よく聞こえます。
そのせいか高音も透き通った良い音で聞こえるような気がします。
録音したファイルのスピーカー再生ではデジタル信号処理による Clear Audio+ という Sony の得意技も設定できます。(そこまでやるか
調子にのって音楽ファイルを SD メモリーにいれて再生させてみたところそこそこ楽しめます。
残念ながら音楽ファイルを綺麗な音で楽しむという所まではいかないようです。
音楽用に設計された機種と比べること自体間違いのですがついつい・・・ Sony だから期待していまいました。
さて、次に使い勝手の良さをみていきます。
時計、チャンネル設定、予約設定などは取扱説明書を読めば簡単に設定できます。
チャンネル設定は今時仕様で地域を選んだら自動でプリセットされます。楽ちんです。
ただし、この取扱説明書の文字が小さく読みにくい。
取扱説明書を2倍くらいの大きさにして大きな文字と絵にしてほしいですね。
コスト的に厳しいかもしれないけど取扱説明書は購入者が絶対に必要とし必ず目を通すものだということを忘れないでほしい。
それら設定をする操作ボタンは解りやすく日本語で表記されています。
これら操作ボタンはラジオのフロントとトップに集中されています。



はじめはこんなにたくさんあって使いにくいかもしれないと心配しましたが実に合理的な配置になっていると感心させられます。
これら操作のインフォメーションは中央の小さな液晶パネルに表示されます。
バックライトのオン、オフも設定できるし、解りやすくていいです。(白色バックライトはいいね。)
昔のように周波数パネル上の棒をダイヤルを回しながら左右に動かして放送局を選択するという味わい深い操作を必要としません。(^_^;)
お気に入りの放送局を五つ登録できる機能までついてます。(便利です。)
このラジオのマニアックな使い方は語学学習にあるといっても過言ではありますせん。
私には必要の無い機能なのですが、録音したファイルの再生スピードの調整ができます。
リピート機能もあります。
ディクテーション再生機能も搭載しているので聞いて、書いてといった学習に最適ですね。
語学の学習に役立つことは間違いないでしょう。
このラジオはステレオマイクを内蔵しているので自分の発音を録音して確認するなど楽しみ方はいろいろありそうです。
このラジオに録音したファイルをパソコンで管理するのに sound organizer というアプリケーションが内蔵メモリーに付属されています。
ラジオとパソコンを USB ケーブルでつないぐと sound organizer のインストールが開始されほぼ自動で設定終了し、使えるようになります。
録音ファイルのコピーや移動などパソコン上でできます。
ラジオに音楽ファイルなどを転送して楽しむこともできます。
私の家にあったラジオ(ラジカセは除く)の電源はすべて乾電池でした。
このラジオの電源はリチウムイオン電池を内蔵していて AC アダプタを使用してでの使用、 AC アダプタ無しで内蔵リチウムイオン電池だけでの使用が可能です。
内蔵充電池があるというのはうれしいです!
しかも単三アルカリ乾電池 4 本を併用して使用すると最大約 20 時間使えるそうです。
以上、ゆっちの散財記録でした。
SONY ICZ-R250TV
TAGS: Computer,General |
2015年3月20日6:48 AM |
JavaFX
JDK8u40 で追加された Spinner と Dialog を試してみた。
このエントリーで Arrow button をマウスクリックして操作した場合、呼び出す Dialog を Modality.APPLICATION_MODAL または Modality.WINDOW_MODAL に設定すると
Spinner のインクリメントもしくはデクリメントが止まらないという不思議な現象に悩まされました。
キーボードのカーソルキーでの操作では期待通りに正常に動きます。
なんでマウスで Arrow button をクリックして操作するといけないのか?
MousePressed がブロックされずに押しっぱなし状態で SpinnerBehavior クラスの startSpinning(boolean increment) の Timeline が動いちゃってるようです。
そこで、愚かなアイディアですが MouseReleased が発生してから Dialog を呼び出しちゃえってやってみたら期待通りに動いてくれました。
ごめんなさい。こんな方法しか思いつきませんでした。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
|
spinner.valueProperty().addListener((ov, oldValue, newValue) -> { System.out.println(newValue); spinner.setOnMouseReleased(e -> { if (newValue <= 30_000 && poor.getValue()) { poor.setValue(Boolean.FALSE); showPoorDialog(); } if (newValue >= 70_000 && rich.getValue()) { rich.setValue(Boolean.FALSE); showRichDialog(); } }); spinner.setOnKeyReleased(e -> { if (newValue <= 30_000 && poor.getValue()) { poor.setValue(Boolean.FALSE); showPoorDialog(); } if (newValue >= 70_000 && rich.getValue()) { rich.setValue(Boolean.FALSE); showRichDialog(); } }); }); |
と言うことでお終いです。
これってやっぱりバグなんだろうか?
追記:Jose Pereda さんよりコメントをいただきました。
それによると SpinnerSkin class に問題があるようです。
詳しくは Jose さんのコメントをご覧ください。
あわせてこの問題に対する素晴らしい解決方法を提示してくれましたのでエントリー本文にも記載させていただきます。
素晴らしいコードをありがとうございました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
|
private SpinnerBehavior<Integer> beh; @Override public void initialize(URL url, ResourceBundle rb) { spinner.valueProperty().addListener((ov, oldValue, newValue) -> { System.out.println(newValue); if (beh == null) { beh = (SpinnerBehavior) ((SpinnerSkin) (spinner.getSkin())).getBehavior(); spinner.focusedProperty().addListener((obs, b, b1) -> { if (b && !b1) { beh.stopSpinning(); } }); } if (newValue <= 30_000 && poor.getValue()) { poor.setValue(Boolean.FALSE); showPoorDialog(); } if (newValue >= 70_000 && rich.getValue()) { rich.setValue(Boolean.FALSE); showRichDialog(); } }); } |
TAGS: JavaFX |
2015年3月13日12:02 AM |
JavaFX
JDK8u40 でやっと Dialog が追加されました。
これでお手軽に使えることになります。
あと Spinner も、そして Formatted Text も追加されました。
今回は Spinner と Dialog をサクッと使ってみたいと思います。
毎月のお小遣いの金額を Spinner で入力してある金額より低いもしくは高い場合に Dialog を出すという超シンプルなものです。
しかし、私はこれでドツボにはまり、未だに改善策を見いだせずに困っています。
心優しい優秀な Java プログラマのかたがこの記事を見ていたらどうか解決方法をお教えくださいませ。
Dialog の設定を Modality.APPLICATION_MODAL と Modality.WINDOW_MODAL にすると思わぬ事態が発生します。
それではプログラムのソースコード及び動画を貼っておきます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
|
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?> <?import javafx.scene.text.*?> <?import java.lang.*?> <?import java.util.*?> <?import javafx.scene.*?> <?import javafx.scene.control.*?> <?import javafx.scene.layout.*?> <AnchorPane id="AnchorPane" fx:id="anchorPane" prefHeight="50.0" prefWidth="272.0" xmlns="http://javafx.com/javafx/8.0.40" xmlns:fx="http://javafx.com/fxml/1" fx:controller="jp.yucchi.hellospinneranddialog.FXMLDocumentController"> <children> <Label fx:id="label_1" layoutX="14.0" layoutY="42.0" minHeight="16" minWidth="69" text="私の毎月のお小遣いは" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="10.0" AnchorPane.topAnchor="10.0"> <font> <Font size="14.0" /> </font></Label> <Spinner fx:id="spinner" layoutX="145.0" layoutY="10.0" prefHeight="30.0" prefWidth="80.0" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="145.0" AnchorPane.topAnchor="10.0" /> <Label fx:id="label_2" layoutX="225.0" layoutY="10.0" text="です。" AnchorPane.bottomAnchor="10.0" AnchorPane.leftAnchor="235.0" AnchorPane.topAnchor="10.0"> <font> <Font size="14.0" /> </font> </Label> </children> </AnchorPane> |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33
|
package jp.yucchi.hellospinneranddialog; import javafx.application.Application; import javafx.fxml.FXMLLoader; import javafx.scene.Parent; import javafx.scene.Scene; import javafx.stage.Stage; /** * * @author Yucchi */ public class HelloSpinnerAndDialog extends Application { @Override public void start(Stage stage) throws Exception { Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml")); Scene scene = new Scene(root); stage.setScene(scene); stage.setTitle("毎月のお小遣いは?"); stage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
|
package jp.yucchi.hellospinneranddialog; import java.net.URL; import java.util.ResourceBundle; import javafx.beans.property.BooleanProperty; import javafx.beans.property.SimpleBooleanProperty; import javafx.fxml.FXML; import javafx.fxml.Initializable; import javafx.scene.control.Alert; import javafx.scene.control.Alert.AlertType; import javafx.scene.control.ButtonType; import javafx.scene.control.Label; import javafx.scene.control.Spinner; import javafx.scene.control.SpinnerValueFactory; import javafx.scene.layout.AnchorPane; import javafx.stage.Modality; /** * * @author Yucchi */ public class FXMLDocumentController implements Initializable { private BooleanProperty poor; private BooleanProperty rich; @FXML AnchorPane anchorPane; @FXML private Label label_1; @FXML private Spinner<integer> spinner; @FXML private Label label_2; @Override public void initialize(URL url, ResourceBundle rb) { poor = new SimpleBooleanProperty(true); rich = new SimpleBooleanProperty(true); // 0 から 100,000 まで 5,000 ずつ加減算する、初期値は 50,000 の Spinner spinner.setValueFactory(new SpinnerValueFactory.IntegerSpinnerValueFactory(0, 100_000, 50_000, 5_000)); // // Spinner のデザインを水平にする // spinner.getStyleClass().add(Spinner.STYLE_CLASS_ARROWS_ON_RIGHT_HORIZONTAL); spinner.valueProperty().addListener((ov, oldValue, newValue) -> { System.out.println(newValue); if (newValue <= 30_000 && poor.getValue()) { poor.setValue(Boolean.FALSE); showPoorDialog(); } if (newValue >= 70_000 && rich.getValue()) { rich.setValue(Boolean.FALSE); showRichDialog(); } }); } private void showPoorDialog() { Alert alert = new Alert(AlertType.WARNING, "もう少しお小遣いを増やしましょう。", ButtonType.OK); alert.initModality(Modality.NONE); alert.initOwner(anchorPane.getScene().getWindow()); alert.getDialogPane().setHeaderText("少ないですね。"); alert.showAndWait() .filter(response -> response == ButtonType.OK) .ifPresent(response -> System.out.println(":p")); } private void showRichDialog() { Alert alert = new Alert(AlertType.INFORMATION, "お金で愛は買えないが、お金で愛は潤います。", ButtonType.OK); alert.initModality(Modality.NONE); alert.initOwner(anchorPane.getScene().getWindow()); alert.getDialogPane().setHeaderText("幸せですね!"); alert.showAndWait() .filter(response -> response == ButtonType.OK) .ifPresent(response -> System.out.println(":p")); } } |
Spinner の CSS のあてかたも解らないので入力値を右寄せにしたり色を変えたりとかもしたかったのですがそれはネット上に情報が出てきてからボチボチ勉強していきたいですね。
追記:キーボードからカーソルキー入力では問題ないのでバグの可能性が高いです。
TAGS: JavaFX |
2015年3月8日10:57 AM |
JavaFX
JavaFX の SplitPane の存在は知っていたが使う機会が無かったので使い方を知らないまま今日に至っています。
とりあえず簡単な使い方だけでも知っておこうとググってみたのですが日本語での情報を見つけることができませんでした。(>_<。)
しかたないので API ドキュメントをサラッと 読んで 眺めてみることにしました。
Class SplitPane
http://docs.oracle.com/javase/8/javafx/api/javafx/scene/control/SplitPane.html#getDividerPositions–
縦、横の指定や分割位置などが設定できるようでメソッド数も少なくシンプルなものです。
ただ、私の英語力及び Java 力では理解できないものがあり目から汗が出ています。
Example に sp.setDividerPositions(0.3f, 0.6f, 0.9f); とあるんだけど
最後の引数の 0.9f は無くてもいいんじゃないの?
最後のスペースは自動計算されるはずでは?
なぜなんだろう?
何か意味があるはずなんだろうけど・・・
と言うことでサクッとプログラムを組んで動作確認してみました。
上記のように ? の状態なのでこれであっているか自信はありません。
ラベルをみっつ均等に表示させ、左のラベルは全体の33パーセントより小さくさせない、右のラベルは全体の33パーセントより大きくさせないという制限も付加してみました。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
|
package jp.yucchi.trysplitpane; import javafx.application.Application; import javafx.scene.Group; import javafx.scene.Scene; import javafx.scene.control.Label; import javafx.scene.control.SplitPane; import javafx.scene.layout.StackPane; import javafx.stage.Stage; /** * * @author Yucchi */ public class TrySplitPane extends Application { @Override public void start(Stage primaryStage) { Group root = new Group(); SplitPane sp = new SplitPane(); final StackPane sp1 = new StackPane(); sp1.getChildren().add(new Label("堀北真希")); final StackPane sp2 = new StackPane(); sp2.getChildren().add(new Label("新垣結衣")); final StackPane sp3 = new StackPane(); sp3.getChildren().add(new Label("綾瀬はるか")); sp.getItems().addAll(sp1, sp2, sp3); // 均等に分割 sp.setDividerPositions(0.333f, 0.666f); // 真希ちゃんラベルを33パーセントより小さくさせない。 sp1.minWidthProperty().bind(sp.widthProperty().multiply(0.333)); // はるかちゃんラベルを33パーセントより大きくさせない。 sp3.maxWidthProperty().bind(sp.widthProperty().multiply(0.333)); root.getChildren().add(sp); Scene scene = new Scene(root, 300, 30); sp.prefWidthProperty().bind(scene.widthProperty()); sp.prefHeightProperty().bind(scene.heightProperty()); primaryStage.setTitle("Hello SplitPane"); primaryStage.setScene(scene); primaryStage.show(); } /** * @param args the command line arguments */ public static void main(String[] args) { launch(args); } } |
このプログラムの実行結果は下図のようになります。
初期状態

左の Divider を右へドラッグして左のラベルを大ききします。

左の Divider を左へドラッグして左のラベルを小さくしようとしますが制限がかかっていて小さくなりません。

右の Divider を右へドラッグして中央のラベルを大きくします。

右の Divider 左へドラッグして右のラベルを大きくしようとしますが制限がかかっておおきくなりません。

これって以外と便利に使えるかもしれないですね。
なんで日本語の情報がないんだろう?
シンプルすぎてスルーされているんだろうか?
最後に、ラベルのテキストは私個人の好みであり所属する会社の公式な好みではありません。(ヲヒ
TAGS: JavaFX |
2015年2月28日7:10 AM |
« 古い記事
新しい記事 »