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

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

JavaFX: ImageView内で画像をドラッグしながら移動させる方法

   

JavaFXのImageViewエリア内ではみ出ている画像をマウスドラッグで移動する方法について書きます。

 

画像だけだとわかりにくいので動画にしました。最初は動画を撮りはじめの影響か動きが渋いですが途中からスムースにマウスドラッグで画像が移動してくれています。

 

この動きは簡単そうに見えていますが、実はマウスドラッグのたびに画像を適宜トリミングしています。その点については前回書いた通りです。

 

広告

 

前回同様、SceneBuilderでImageViewを設置しました。IDはimageViewとしています。

 

イベントとして、「On Mouse Dragged」と「On Mouse Pressed」に以下のメソッドを設定しています。Pressイベントでまずドラッグ前の位置を記憶し、ドラックのたびに開始位置からどれだけマウスを動かしたか算出して、それを画像トリミングの際のオフセット値にするためです。

 

FXMLファイルは以下のとおりになります。

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

<?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="ImageViewTest2">
  <children>
    <ImageView fx:id="imageView" fitHeight="262.0" fitWidth="575.0" layoutX="13.0" layoutY="61.0" onMouseDragged="#onMouseDrag" onMousePressed="#onMousePress" pickOnBounds="true" preserveRatio="true" />
  </children>
</Pane>
 

 

本体のソースは以下の通りです。解説はソースコード中に入れているので適宜確認してください。

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

public class ImageViewTest2 extends Application implements Initializable {
  @FXML private ImageView imageView;
  private Image image;
  private int w;
  private int h;
  private int offsetX;
  private int offsetY;
  private int moveX;
  private int moveY;

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

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

  @Override
  public void initialize(java.net.URL url, java.util.ResourceBundle bundle) {
    //初期状態は画像左上端でImageViewサイズに
    //トリミングして表示しておく
    //w, hはImageViewサイズの記憶
    image = new Image("image.jpg");
    w = (int) imageView.getFitWidth();
    h = (int) imageView.getFitHeight();
    offsetX = 0;
    offsetY = 0;
    WritableImage cutimg = new WritableImage(image.getPixelReader(), offsetX, offsetY, w, h);
    imageView.setImage(cutimg);
  }

  //ドラッグ前の開始位置を記憶
  @FXML
  public void onMousePress(MouseEvent event) {
    moveX = (int) event.getX();
    moveY = (int) event.getY();
  }

  //ドラッグしながら画像のオフセット位置を変えて
  //ImageViewサイズにトリミング
  @FXML
  public void onMouseDrag(MouseEvent event) {
    int limitX = (int) (image.getWidth()-imageView.getFitWidth());
    int limitY = (int) (image.getHeight()-imageView.getFitHeight());
    //オフセット位置の計算。40は速度を落とすためのもの
    offsetX = offsetX - ( (int) ((event.getX() - moveX) / 40 ) );
    offsetY = offsetY - ( (int) ((event.getY() - moveY) / 40 ) );
    //オフセット位置が画像サイズを超えないようリミッターをかけている
    if(offsetX < 0) offsetX=0;
    if(offsetY < 0) offsetY=0;
    if(offsetX > limitX) offsetX=limitX;
    if(offsetY > limitY) offsetY=limitY;
    //トリミングして表示
    WritableImage cutimg = new WritableImage(image.getPixelReader(), offsetX, offsetY, w, h);
    imageView.setImage(cutimg);
  }
}
 

 

広告

 - Java