JavaFXでサイズ変更可能なcanvasを作る
resizableなcanvasをJavaFXで作ろうよ、というお話。
JavaFX Tip 1: Resizable Canvas | Java Code Geeks
上記記事を参考に
Javaは8です。やることは以下。
- Canvasのサブクラスを作る
- isResizable()メソッドをオーバーライド
- prefWidth(),prefHeight()メソッドをオーバーライド
- 画面サイズが変わったときに再描画する(線のサイズも変わる)listenerをCanvasのwidth,heightプロパティに追加
- 親ペインのwidth,heightプロパティにCanvasのwidth,heightプロパティをバインド
Tip1ResizableCanvas.java
import javafx.application.Application; import javafx.scene.Scene; import javafx.scene.canvas.Canvas; import javafx.scene.canvas.GraphicsContext; import javafx.scene.layout.StackPane; import javafx.scene.paint.Color; import javafx.stage.Stage; /** * Tip 1: A canvas resizing itself to the size of * the parent pane. */ public class Tip1ResizableCanvas extends Application { class ResizableCanvas extends Canvas { public ResizableCanvas() { // Redraw canvas when size changes. widthProperty().addListener(evt -> draw()); heightProperty().addListener(evt -> draw()); } private void draw() { double width = getWidth(); double height = getHeight(); GraphicsContext gc = getGraphicsContext2D(); gc.clearRect(0, 0, width, height); gc.setStroke(Color.RED); gc.strokeLine(0, 0, width, height); gc.strokeLine(0, height, width, 0); } @Override public boolean isResizable() { return true; } @Override public double prefWidth(double height) { return getWidth(); } @Override public double prefHeight(double width) { return getHeight(); } } @Override public void start(Stage stage) throws Exception { ResizableCanvas canvas = new ResizableCanvas(); StackPane stackPane = new StackPane(); stackPane.getChildren().add(canvas); // Bind canvas size to stack pane size. canvas.widthProperty().bind( stackPane.widthProperty()); canvas.heightProperty().bind( stackPane.heightProperty()); stage.setScene(new Scene(stackPane)); stage.setTitle("Tip 1: Resizable Canvas"); stage.show(); } public static void main(String[] args) { launch(args); } }
対角線上に線が引かれていますが
ウィンドウサイズを横にのばすと、それに合わせて線もビヨーン。
縦にのばしても同様に。
以下、メモしたことをそのまま。
何書いてるのかよくわからんですが・・・。まだまだ調べものしなきゃなんない。
何やらjavafxをいろいろインポートしていく
application.Application
scene.Scene
scene.canvas.Canvas
scene.canvas.GraphicsContext
scene.layout.StackPane
scene.paint.Color
stage.Stage
Applicationを拡張してTip1ResizableCanvasを作る。
その中でCanvasを拡張してResizableCanvasを作る。
そのコンストラクタの内容は
サイズが変わったら再描画する
widthProperty(),heightProperty()に(の?)addListener methodを使う。これで再描画のトリガーセット。
evt -> draw()がわからん。draw()をevtが指しているの?(*要はJava8がわかっとらん)
んで、draw()の中身は
getWidth(),getHeight()にそれぞれwidth,heightをアサイン。
GraphicsContextクラス型のgcをgetGraphicsContext2D()にアサイン。インスタンス化。
.clearRect()で四角を作る?(0, 0, width, height) width,heightにgetWidth,getHeightで取得した値が入る。これで画面のサイズを変更できるのか。
で線を描く。
setStroke(色はレッド)、strokeLineで(0,0)から(width, height)まで。つまり対角線ですな。
そしてそれとは逆の対角線を書く。(0, height)左下の角から、(width,0)右上の角まで
isResizableをオーバーライド trueを返す。これでサイズ変更おkにしている?
prefWidth,prefHeightをオーバーライド。ここで引数はそれぞれheight,widthになっている。つまり反対だ。戻り値がgetWidth,getHeightと、引数とは逆?になっている。それぞれのメソッドでwidth,heightをゲットしている、というのは一目見ればわかるが、引数が逆とはこれいかに。
startをオーバーライド(Application classの抽象メソッド) 例外を投げるようにしてある。
Resizable classのオブジェクト作成(canvas)
StackPaneクラス型でstackPaneというオブジェクト作成
.getChildren()のさらに?.addで引数canvas つまりStackPaneにcanvasを追加している
canvasのサイズをstack paneのサイズにバインド、合わせている。
canvas.widthProperty().bind(stackPane.widthProperty());
heightも同様に
これによってstack paneのサイズが変われば、canvasのサイズも変わる、ということ?
stage.setStage(new Scene(stackPane));
stackPaneを引数としてSceneオブジェクト作成し、それをさらにsetStageの引数とする。これがラップというやつなのか?要確認
あとはsetTitileと.show()
mainでやっていることはargsを引数としてlaunchさせることだけ。これはJavaFXを扱う際には必須のことなのか、よくわからんがそういうことだ。
円で書いてみるとどうなるんだろうねっと。真ん中に円を作ってみるのも良いかもしらん。
これ、デフォの画面サイズはどこで決定されているのだろう?
draw()のgetWidth(),getHeight()の値にwidth,heightがアサインされているので決まっていると思うが。