非IT企業に勤める中年サラリーマンのIT日記

非IT企業でしかもITとは全く関係ない部署にいる中年エンジニア。唯一の趣味がプログラミングという”自称”プログラマー。

JavaFX: ImageViewで画像を表示する(フィッティング・はみ出し・トリミング)

   

JavaFXで画像を表示させるにはImageViewクラスを使います。基本的な使い方について書き留めておきます。

C#なんかで画像を表示させる場合はPoctureBoxクラスを使いますが、これはフィッティングや画像サイズを維持してはみ出したりするのに、PoctureBoxクラスのプロパティで制御します。まあ、だいたいそんなところをイメージすると思いますが、JavaFX/ImageViewクラスは、はみ出す部分をわざわざトリミングさせなければなりません。

さすがJava。偏狭もここまで来るともはや嫌がらせレベルです(笑)。

広告

今回のサンプルのImageViewクラスエリアについて

今回作ったサンプルプのImageViewエリアは以下の通りフォームの中央辺りにあります。かなり横長ですが画像の表示のバリエーションをもたせるために故意にそうしています。ボタンは2つあってそれぞれにonActuonを以下のように割り当てています。

 

上の図はSceneBuilderのスクショです。ImageViewのIDをimageViewとしました。以下サンプルプログラムでimageViewというオブジェクトが現れますが、それはImageViewオブジェクトとなります。

 

画像はフリー素材サイトから以下の画像を拝借しました。

 

 

画像をそのまま表示させる場合

単純に画像を読み込んでImageViewに貼り付けると、全体表示されるように自動でフィッティングしてくれます。今回はImageViewの高さ狭いので高さを合わせて縮小した形になっています。

 

ソースコードは以下のとおりたった2行で表示できます。

//import javafx.scene.image.*;
Image image = new Image("image.jpg");
imageView.setImage(image);
 

 

画像サイズをオリジナルサイズにしてはみ出させる

画像を縮小させずオリジナルサイズのまま、ImageViewエリアからはみ出すように表示させる方法です。以下のような表示になります。

 

これがC#ならプロパティをちょっと変えれば実現できるのですが、Javaはそうはいきません。余分な箇所をトリミングしてあげる必要があります。面倒くさいです。

以下のように左上の一部しか表示させていません。それ以外のところはトリミングします。

 

トリミングにはWritableImageクラスを使います。

まずはimageViewクラスの縦横サイズを取得して(w1, h1)、画像の左上を起点にそのサイズでトリミングしたのがcutimg。それをImageViewエリアに表示させているわけです。

Image image = new Image("image.jpg");
int w1 = (int) imageView.getFitWidth();
int h1 = (int) imageView.getFitHeight();
WritableImage cutimg = new WritableImage(image.getPixelReader(), 0, 0, w1, h1);
imageView.setImage(cutimg);
 

 

WritableImageクラスの引数で「0, 0, ..」とゼロが2つ並んでいますが、これはオフセット値で左上を起点にしていることを意味しています。ここをいじるとトリミングの起点の場所を変えることができます。

 

横幅のみをフィッティングさせる

今度は横幅をフィッティングさせて縦方向はトリミングする方法です。

 

以下のような上段のエリアのみ表示させて、マスキングしたところはカットします。

 

ソースコードは以下の通り。画像の横幅(w2)はそのままで、縦方向をImageViewの縦横割合から算出します。A1:B1=A2:B2 → A1・B2=B1・A2というヤツですね。小学校(中学?)の時習いました。

Image image = new Image("image.jpg");
int w1 = (int) imageView.getFitWidth();
int h1 = (int) imageView.getFitHeight();
int w2 = (int) image.getWidth();
int h2 = (int) image.getHeight();

WritableImage cutimg = new WritableImage(image.getPixelReader(), 0, 0, w2, (h1*w2)/w1);
imageView.setImage(cutimg);
 

 

ソースコード全文

ソースコード全文を下記しておきます。まずはFXMLソースです。

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.scene.control.Button?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.Pane?>

<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/9" xmlns:fx="http://javafx.com/fxml/1" fx:controller="ImageViewTest">
  <children>
    <ImageView fx:id="imageView" fitHeight="143.0" fitWidth="575.0" layoutX="13.0" layoutY="109.0" pickOnBounds="true" preserveRatio="true" />
    <Button layoutX="138.0" layoutY="21.0" mnemonicParsing="false" onAction="#onClick2" text="横フィット" />
    <Button layoutX="25.0" layoutY="21.0" mnemonicParsing="false" onAction="#onClick1" text="画像サイズのまま" />
  </children>
</Pane>
 

 

こちらがJava本体です。起動時にトリミングしない画像(ImageViewエリアまで縮小)を表示させておいて、ボタンで表示方法を変えるようになっています。

import javafx.application.Application;
import javafx.fxml.*;
import javafx.scene.*;
import javafx.stage.Stage;
import javafx.scene.layout.*;
import javafx.event.ActionEvent;
import javafx.scene.image.*;

public class ImageViewTest extends Application implements Initializable {
  @FXML private ImageView imageView;
  private Image image;

  public static void main(String[] args) {
    launch(args);
  }

  @Override
  public void start(Stage stage) throws Exception{
    Pane root = FXMLLoader.load(getClass().getResource("ImageViewTest.fxml"));
    stage.setTitle("ImageView Test");
    stage.setScene(new Scene(root));
    stage.show();
  }

  @Override
  public void initialize(java.net.URL url, java.util.ResourceBundle bundle) {
    image = new Image("image.jpg");
    imageView.setImage(image);
  }

  @FXML
  public void onClick1(ActionEvent e) {
    int w1 = (int) imageView.getFitWidth();
    int h1 = (int) imageView.getFitHeight();

    WritableImage cutimg = new WritableImage(image.getPixelReader(), 0, 0, w1, h1);
    imageView.setImage(cutimg);
  }

  @FXML
  public void onClick2(ActionEvent e) {
    int w1 = (int) imageView.getFitWidth();
    int h1 = (int) imageView.getFitHeight();
    int w2 = (int) image.getWidth();
    int h2 = (int) image.getHeight();

    WritableImage cutimg = new WritableImage(image.getPixelReader(), 0, 0, w2, (h1*w2)/w1);
    imageView.setImage(cutimg);
  }
}
 

 

広告

 - Java