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

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

JavaFXのフォームを画像キャプチャする方法

   

JavaFXでフォームの画像キャプチャする方法です。JavaFXではタイトルバーを含めたフォームのキャプチャはできなくて、VBoxやPaneのようなパネル系クラスの親にNodeというクラスが合って、そこにsnapshotというメソッドがあります。そのメソッドを使ってパネルごとキャプチャすることができます。

広告

サンプルプログラムの完成形

起動するとこんな感じです。「キャプチャ」というボタンを押すと下段のパネルが配置されたコントロールごとキャプチャされます。

 

キャプチャボタンを押すと下図の通りカレントディレクトリにtest.pngという画像が現れます。

 

開くと以下の通り、下段のパネル部分がキャプチャされました。

ソースコード

ソースコードの前にまずはSceneBuilderで作ったUI部分です。

キャプチャというボタンにonClickというアクションIDを付けて、下段のPaneにmainPaneとID付しました。それ以外は適当に配置しています。CheckBoxもTableViewも適当に配置していて特に制御しません。mainPaneごとキャプチャするために置いたものです。

FXMLのソースは以下の通りです。

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

<?import javafx.scene.control.Button?>
<?import javafx.scene.control.CheckBox?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.VBox?>

<VBox 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="FormCapture">
  <children>
    <Pane prefHeight="64.0" prefWidth="600.0">
      <children>
        <Button layoutX="14.0" layoutY="9.0" mnemonicParsing="false" onAction="#onClick" text="キャプチャ" />
      </children>
    </Pane>
    <Pane fx:id="mainPane" prefHeight="381.0" prefWidth="600.0">
      <children>
        <CheckBox layoutX="53.0" layoutY="38.0" mnemonicParsing="false" text="CheckBox" />
        <TableView layoutX="45.0" layoutY="80.0" prefHeight="200.0" prefWidth="407.0">
          <columns>
            <TableColumn prefWidth="75.0" text="C1" />
            <TableColumn prefWidth="75.0" text="C2" />
          </columns>
        </TableView>
        <Button layoutX="174.0" layoutY="35.0" mnemonicParsing="false" prefHeight="24.0" prefWidth="124.0" text="Button" />
      </children>
    </Pane>
  </children>
</VBox>
 

 

次に本体のJavaのソースコードです。解説は後述。

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.*;
import javax.imageio.*;
import javafx.embed.swing.*;
import java.io.*;

public class FormCapture extends Application implements Initializable {
  @FXML private Pane mainPane;

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

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

  @Override
  public void initialize(java.net.URL url, java.util.ResourceBundle bundle) {
    //今回ここを使わなかった...。
  }

  @FXML
  public void onClick(ActionEvent e) {
    WritableImage img = mainPane.snapshot(new SnapshotParameters(), null);
    try{
      ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", new File("test.png"));
    }catch(Exception ex){ //悪手とされるExceptionでキャッチ。ゆるして。
      System.out.println(ex);
    }
    System.out.println("OK");
  }
}
 

 

パネルのキャプチャは以下の1行部分です。mainPaneの親クラス(Node)のsnapshotメソッドを使ってキャプチャします。

WritableImage img = mainPane.snapshot(new SnapshotParameters(), null);
 

 

で、最後にpng形式で保存するのが以下の一文。これも一行だけで至って簡単。

ImageIO.write(SwingFXUtils.fromFXImage(img, null), "png", new File("test.png"));
 

 

広告

 - Java