FX - ImageView の大きさを他のノードと連動させる
ウィンドウサイズを変更したときに、 ImageView
の表示も大きくしたり小さくしたりしたい、そんな願望を叶えようと四苦八苦したときのメモ。
色々試行錯誤した結果なので、正しさは保障できない。
Stage と連動させた場合
実装
main.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.BorderPane?>
<BorderPane fx:controller="sample.javafx.MainController" xmlns="http://javafx.com/javafx/8.0.121" xmlns:fx="http://javafx.com/fxml/1">
<center>
<ImageView fx:id="imageView" fitHeight="150.0" fitWidth="200.0" pickOnBounds="true" preserveRatio="true" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
MainController.java
package sample.javafx;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.stage.Stage;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@FXML
private ImageView imageView;
public void initStage(Stage stage) {
stage.setWidth(300);
stage.setHeight(200);
imageView.fitWidthProperty().bind(stage.widthProperty());
imageView.fitHeightProperty().bind(stage.heightProperty());
}
@Override
public void initialize(URL location, ResourceBundle resources) {
Image image = new Image(Paths.get("./image/shirakawago.jpg").toUri().toString());
imageView.setImage(image);
}
}
Main.java
package sample.javafx;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
public static void main(String[] args) {
Application.launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception {
FXMLLoader loader = new FXMLLoader(this.getClass().getResource("/main.fxml"));
Parent root = loader.load();
MainController controller = loader.getController();
controller.initStage(primaryStage);
Scene scene = new Scene(root);
primaryStage.setScene(scene);
primaryStage.show();
}
}
実行結果
説明
-
ImageView
のfitWidth
プロパティとfitHeight
プロパティを、Stage
のwidth
プロパティとheight
プロパティにバインドさせる - 注意なのが、
Stage
のwidth
とheight
にあらかじめ値を設定しておく必要があるという点- 何も設定していないと、
Stage
のwidth
とheight
は初期値がNaN
になる - その
width
,height
プロパティにImageView
のfitWidth
,fitHeight
プロパティをバインドすると、どうやら設定しているImage
のオリジナルサイズで初期化されてしまうっぽい
- 何も設定していないと、
- ただ、よく見てみるとウィンドウサイズを小さくしたときに画像の下部分が隠れてしまっている(右下の女性の姿を見ると分かりやすい)
この値には、オペレーティング・システムで追加できる、タイトル・バーなどのすべての装飾が含まれます。
- ということなので、おそらくタイトルバーの高さだけ画像が隠れてしまっているっぽい
シーングラフのルートに合わせる
実装
MainController.java
package sample.javafx;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import java.net.URL;
import java.nio.file.Paths;
import java.util.ResourceBundle;
public class MainController implements Initializable {
@FXML
private BorderPane borderPane;
@FXML
private ImageView imageView;
public void initStage(Stage stage) {
stage.setWidth(300);
stage.setHeight(200);
}
@Override
public void initialize(URL location, ResourceBundle resources) {
Image image = new Image(Paths.get("./image/shirakawago.jpg").toUri().toString());
imageView.setImage(image);
imageView.fitWidthProperty().bind(borderPane.widthProperty());
imageView.fitHeightProperty().bind(borderPane.heightProperty());
}
}
実行結果
説明
- シーングラフのルートである
BorderPane
のwidth
,height
プロパティとImageView
のfitWidth
,fitHeight
プロパティをバインドしておく - こちらも
Stage
のwidth
,height
に初期値を設定しておかないと、Image
のオリジナルサイズになってしまうっぽい - ウィンドウサイズを小さくしても画像の下が隠れることもなく、うまくいっているっぽい
ルート以外のノードと連動させる
他のノードが入ってきた場合
上述の方法は、あくまでシーングラフ内に他のノードが一切ない状態なので、いわゆるイメージビューアみたいなものしか実現できない。
試しに、シーングラフ内に他のノードを追加してみる。
実装
実行結果
説明
- ラベルのサイズだけ領域が使用されるため、ルートノードのサイズと
ImageView
のサイズを連動させると、画像を表示する範囲が足りなくなる
とりあえず画像表示領域用にノードを追加してみる
実装
-
ImageView
を囲むように新しくノード(BorderPane
)を追加-
width
,height
関係はとりあえず全てデフォルトのUSE_COMPUTED_SIZE
にしている
-
-
ImageView
は、この新しく追加したBorderPane
のwidth
,height
プロパティと連動するように実装しておく
実行結果
説明
- ちょっと分かりにくいが、画像がオリジナルサイズで表示されていて、左上の部分だけが見えている
- なぜ
BorderPane
がルートノードのときはOKで、子供のノードになるとこういう動きになるのか、正直なところ自分も原理は理解できていない
非ルートノードに連動させる
実装
実行結果
説明
-
Min Width
とMin Height
を、それぞれ0
に設定する- おそらく、デフォルトの
USE_COMPUTED_SIZE
にしていると、領域の最小サイズが子要素のサイズ(ここではImageView
のサイズ)と一致してしまうので、最小サイズ = 画像のサイズになってしまい、1つ前のような動きになったのではないかと想像している(あくまで想像) - ただ、そうだとすると
BorderPane
がルートノードのときも条件は同じはずなので、そっちで同様の状態にならなかった理由はよくわからない
- おそらく、デフォルトの
- とりあえず、非ルートノードとサイズを連動させる場合は、
Min Width
,Min Height
をUSE_COMPUTED_SIZE
,USE_PREF_SIZE
以外の何らかの値にしておけば、良い感じになるっぽい
まとめ
- 共通
-
Stage
の width
, height
を設定しておく
-
ImageView
の fitWidth
, fitHeight
プロパティを、連動させたいノードの width
, height
プロパティにバインドする
- 連動させるノードがルートノードでない場合
- ノードの
Min Width
, Min Height
を USE_COMPUTED_SIZE
, USE_PREF_SIZSE
以外の何らかの値にしておく
-
Stage
のwidth
,height
を設定しておく -
ImageView
のfitWidth
,fitHeight
プロパティを、連動させたいノードのwidth
,height
プロパティにバインドする
- ノードの
Min Width
,Min Height
をUSE_COMPUTED_SIZE
,USE_PREF_SIZSE
以外の何らかの値にしておく
Author And Source
この問題について(FX - ImageView の大きさを他のノードと連動させる), 我々は、より多くの情報をここで見つけました https://qiita.com/opengl-8080/items/29c3ef163f41ee172173著者帰属:元の著者の情報は、元のURLに含まれています。著作権は原作者に属する。
Content is automatically searched and collected through network algorithms . If there is a violation . Please contact us . We will adjust (correct author information ,or delete content ) as soon as possible .