伸縮可能なボックス
JavaFX面白いのに反応がほとんどないのが悲しい今日この頃。
さて、こんな感じのGUIで、ボックスの端をマウスでドラッグすることで値を変化させたい、ありがちなコントロールかと思います。
JavaFXで作ってみました。動くサンプルはこちらから。
結構、手の込んだ事をしないと実装できなそうな気がしますが、JavaFXだと80行程度で実現できます。
ソース解説
public class ResizableBox extends CustomNode { // 中略 }
基本的にカスタムコンポーネント(Node)を作成するにはCustomNode のサブクラスを作成し、createメソッドでカスタムコンポーネントを返します。
override function create():Node { return Group { content: [ Rectangle { // Right x: bind x + width - 5, y: bind y - 5 width: 10, height: bind height + 10 fill: Color.LIGHTBLUE opacity: bind opacityRight onMouseEntered: function(e) { println(e); opacityRight = 0.8; cursor = Cursor.H_RESIZE; } onMouseExited: function(e) { println(e); opacityRight = 0.0; cursor = Cursor.DEFAULT; } onMouseDragged: function(e) { dragging = true; draggingValue = e.dragX as Integer; println(e); } onMouseReleased: function(e) { update(); println(e); } } Rectangle { // Main box x: bind x, y: bind y width: bind width, height: bind height fill: color stroke: Color.BLACK opacity: bind opacityBox } Rectangle { // resizable box x: bind x, y: bind y width: bind width + draggingValue, height: bind height fill: color stroke: Color.BLACK opacity: bind 1.0 - opacityBox } Text { x: bind x + 20, y: bind y + height - 10 content: bind toLabelString(this.width as Integer) } ] } }
返すNodeは、メインのボックス、伸縮時に表示するボックス、右端に表示される強調ボックス、値を表示するラベル用テキストの4つをグループ化しています。Groupもまた1つのNodeとなるため、幾つかのNodeを組み合わせて返すのは基本になるでしょう。
右端に表示されるボックスは、マウスのイベントを処理し、マウスの進入やドラッグ時にステータスを変化させています。ポイントはステータスを変化させているだけで、後はbindにお任せして再描画させている所でしょう。このあたりがJavaFXが簡単に書けるポイントになります。
var dragging:Boolean = false on replace { if (dragging) { opacityBox = 0.4; } else { opacityBox = 1.0; } }; var opacityBox:Number = 1.0;
ここではbindではなくon replaceでステータスがドラッグになった(ならない)時に透明度(opacityBox )の設定を行っています。
opacityBoxはBoxにbindされているので、変更通知は各Boxへ反映されます。