この前、JavaFX の学習がてらに創った ImageGetter というお遊びプログラムでの覚え書きです。
イメージを取得して画像を表示させる処理と、その画像を保存させる処理を書いておきます。
プログラム全体を載せようと思ったのですが無駄に長いのと JavaFX 初心者ということもあって間違ってるかもしれないので。(^_^;)
見たいって人がいれば暇をみつけてプログラム全体をアップするか考えます。
解説は無いですが何をしているか解るようにコメントをいれてあります。
@FXML
public void handleGet(ActionEvent event) {
// イメージ取得時にこれらを非活性化する
prpgressIndicator.setVisible(true);
timeLimit.setDisable(true);
getButton.setDisable(true);
slider.setDisable(true);
effectCombo.setDisable(true);
saveButton.setDisable(true);
file.setDisable(true);
edit.setDisable(true);
exit.setDisable(true);
img.setDisable(true);
imgUrl_1.setDisable(true);
imgUrl_2.setDisable(true);
imgUrl_3.setDisable(true);
// Task クラスを使い Image を取得し、GUI を更新
Task task = new Task() {
// 戻り値なしの非同期処理 ( キャンセル処理は無し )
@Override
protected Void call() throws Exception {
// ExecutorService 設定
int procs = ManagementFactory.getOperatingSystemMXBean().getAvailableProcessors();
if (procs > 1) {
procs = 2;
}
executor = Executors.newFixedThreadPool(procs);
// CompletableFuture を使い Image を取得
// works は、Image 取得クラスのインスタンス
image = CompletableFuture.supplyAsync(() -> works.getImg(baseUrl, subUrl), executor);
image.thenRun(() -> {
});
try {
target = image.get(limit, TimeUnit.SECONDS);
} catch (InterruptedException | ExecutionException | TimeoutException ex) {
// Good catch! (In the latest Japan, it is an indispensable comment.)
Image temp;
if (limit < 5) {
temp = new Image(getClass().getResource("TimeOut.png").toString());
} else {
temp = new Image(getClass().getResource("out.png").toString());
}
image.complete(temp);
}
try {
target = image.get();
} catch (InterruptedException | ExecutionException ex1) {
// Good catch! (In the latest Japan, it is an indispensable comment.)
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex1);
}
// GUI 更新
Platform.runLater(() -> {
imgView.setImage(target);
timeLimit.setDisable(false);
getButton.setDisable(false);
slider.setDisable(false);
effectCombo.setDisable(false);
saveButton.setDisable(false);
file.setDisable(false);
edit.setDisable(false);
exit.setDisable(false);
img.setDisable(false);
imgUrl_1.setDisable(false);
imgUrl_2.setDisable(false);
imgUrl_3.setDisable(false);
prpgressIndicator.setVisible(false);
Toolkit.getDefaultToolkit().beep();
// ExecutorService 止める
while (true) {
if (image.isDone()) {
executor.shutdown();
}
try {
if (!executor.awaitTermination(2, TimeUnit.SECONDS)) {
executor.shutdownNow();
break;
}
} catch (InterruptedException ex) {
// Good catch! (In the latest Japan, it is an indispensable comment.)
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
break;
}
});
return null;
}
};
new Thread(task).start();
}
@FXML
public void handleSave(ActionEvent event) {
// ImageView だけのスナップショット
WritableImage writableImage = imgView.snapshot(null, null);
// ファイルチューザ
File outFile = fileChooser.showSaveDialog(null);
// 保存
if (outFile != null) {
try {
ImageIO.write(SwingFXUtils.fromFXImage(writableImage, null), "png", outFile);
} catch (IOException ex) {
Logger.getLogger(FXMLDocumentController.class.getName()).log(Level.SEVERE, null, ex);
}
}
}
@Override
public void initialize(URL url, ResourceBundle rb) {
................................................
// ファイルチューザ
fileChooser = new FileChooser();
// タイトル
fileChooser.setTitle("Save Image File");
// フィルター
fileChooser.getExtensionFilters()
.addAll(new ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif"),
new ExtensionFilter("All Files", "*.*"));
}
あと ImageView のサイズ調整に ImageGetter.java の starat メソッドに
FXMLDocumentController.imgView.fitWidthProperty().bind(stage.widthProperty().multiply(0.75));
FXMLDocumentController.imgView.fitHeightProperty().bind(stage.heightProperty().multiply(0.75));
としてます。
縮小率は適当です。(やってることも適当です)
こんなことしなくても良い方法があるかもしれませんが解らなかったので諦めてこうしました。(^_^;)
あと Dialog でも少しはまったのでそのことも書こうかと思ったのですが標準ライブラリでない無いからやめておきます。
なんで Dialog が標準ライブラリでないのか疑問ですがこの先どうなるのかまだ解らないですしね。
最後に、くどいようですが間違ってるかもしれないのでおかしなところがあれば笑って許してくださいね。(^_^)