2021년 11월 21일 일요일

Java FX ImageView API

1. Java FX ImageView API

package com.home.fx;

import javafx.application.Platform;
import javafx.beans.value.ChangeListener;
import javafx.beans.value.ObservableValue;
import javafx.embed.swing.SwingFXUtils;
import javafx.geometry.Pos;
import javafx.scene.control.*;
import javafx.scene.control.ScrollPane.ScrollBarPolicy;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.input.*;
import javafx.scene.layout.StackPane;
import javafx.stage.FileChooser;

import javax.imageio.ImageIO;
import java.awt.image.BufferedImage;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;

import static javafx.embed.swing.SwingFXUtils.fromFXImage;

public class FxImageView {

	ImageView imageView;
	ScrollPane scrollPane;
	Label glassText;
	StackPane glassView;
	StackPane layout;
	Double zoom = 1.0;
	Image image;

	public FxImageView(int fontSize, FxRunnable keyHandle) {
		layout = new StackPane();
	    imageView = new ImageView(); //new Image(new File("D:/a.png").toURI().toString())
	    imageView.setPreserveRatio(true);
	    imageView.setPickOnBounds(true);
		layout.setOnMouseMoved(e -> {
	        if ( e.getX() < layout.getWidth() / 4 || e.getX() > layout.getWidth() * 3 / 4 ) {
	            if ( e.getX() < layout.getWidth() / 4 ) {
	                Platform.runLater(() ->glassText.setText("<"));
	                StackPane.setAlignment(glassView, Pos.BOTTOM_LEFT);
	            } else {
	                Platform.runLater(() ->glassText.setText(">"));
	                StackPane.setAlignment(glassView, Pos.BOTTOM_RIGHT);
	            }
	            glassView.setMaxWidth(layout.getWidth() / 4);
	            glassView.setMaxHeight(layout.getHeight());
	            glassView.setVisible(true);
	        } else {
	            glassView.setVisible(false);
	        }
	        e.consume();
	    });
	    
	    scrollPane = new ScrollPane();
	    scrollPane.setPannable(true);
    	if( fontSize > 0 ) {
    		scrollPane.setStyle("-fx-font-size: " + fontSize + " pt;");
    	}
	    //imageView.fitWidthProperty().bind(scrollPane.widthProperty().subtract(10d));
	    scrollPane.setContent(imageView);
	    scrollPane.vvalueProperty().addListener(new ChangeListener<Number>() {
	        public void changed(ObservableValue<? extends Number> ov,
	        Number old_val, Number new_val) {
	            if ( new_val.equals(1.0) ) {
	            	//runnable.run(KeyCode.RIGHT);
	            }
	            if ( new_val.equals(0.0) ) {
	            	//runnable.run(KeyCode.LEFT);
	            }
	        }
	    });

	    scrollPane.setOnKeyPressed(e -> {
	    	keyHandle.run(e.getCode());
	    });

	    glassText = new Label("");
	    glassText.setStyle("-fx-text-fill: goldenrod; -fx-font: italic 20 \"serif\"; -fx-padding: 0 0 20 0; -fx-text-alignment: center");
	
	    glassView = new StackPane();
	    StackPane.setAlignment(glassText, Pos.CENTER);
	    glassView.getChildren().addAll(glassText);
	    glassView.setStyle("-fx-background-color: rgba(0, 50, 100, 0.1); -fx-background-radius: 10;");
	    glassView.setLayoutX(0);
	    glassView.setLayoutY(0);
	    glassView.setPrefWidth(imageView.getFitWidth() / 4);
	    glassView.setPrefHeight(imageView.getFitHeight() / 4);
	    glassView.setVisible(false);
	    glassView.setOnMouseClicked( e-> {
	        if ( glassText.getText().equals(">") ) {
	        	keyHandle.run(KeyCode.RIGHT);
	        } else {
	        	keyHandle.run(KeyCode.LEFT);
	        }
	    });

	    glassView.focusedProperty().addListener(new ChangeListener<Boolean>() {
            @Override public void changed(ObservableValue<? extends Boolean> observable, Boolean oldValue, Boolean newValue) {
                if( ! newValue.booleanValue() ) {
                    glassView.setVisible(false);
                }
            }
        });

		ContextMenu menu = new ContextMenu();
		addMenuItem(menu, "Copy", () -> {
			if( image != null ) {
				Clipboard clipboard = Clipboard.getSystemClipboard();
				ClipboardContent content = new ClipboardContent();
				content.putImage(image);
				clipboard.setContent(content);
			}
		} );
		addMenuItem(menu, "Save", () -> {
			if( image != null ) {
				try {
					FileChooser fileChooser = new FileChooser();
					FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.png");
					fileChooser.getExtensionFilters().add(extFilter);
					File file = fileChooser.showSaveDialog(null); //stage
					ImageIO.write(fromFXImage(image, null), "png", file);
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		} );
		scrollPane.setContextMenu(menu);

	    StackPane.setAlignment(glassView, Pos.BOTTOM_LEFT);
	    layout.getChildren().addAll(scrollPane, glassView);
	    layout.setStyle("-fx-background-color: silver; -fx-padding: 1;");
	}	

	public StackPane getLayout() { return layout; }
	public void clearGlassView() {
		glassView.setVisible(false);
	}

	public void setImage(Image image) {
		this.image = image;
		imageView.setImage(image);
		imageView.setFitWidth( image.getWidth() * zoom );
		imageView.setFitHeight( image.getHeight() * zoom );
		scrollPane.setVvalue(0.0);
	}
	public void setImage(byte[] image) {
		setImage(new Image(new ByteArrayInputStream(image)));
	}
	public void setImage(BufferedImage image) {
		setImage(SwingFXUtils.toFXImage(image,null));
	}
	public void setContextMenu(ContextMenu menu) {
		scrollPane.setContextMenu(menu);
	}
	public void hideScrollBar() {
    	scrollPane.setHbarPolicy(ScrollBarPolicy.NEVER);
    	scrollPane.setVbarPolicy(ScrollBarPolicy.NEVER);
	}
	public void showScrollBar() {
    	scrollPane.setHbarPolicy(ScrollBarPolicy.AS_NEEDED);
    	scrollPane.setVbarPolicy(ScrollBarPolicy.AS_NEEDED);
		setImage(this.image);
	}

	public void fitWidth() {
		imageView.fitWidthProperty().bind(scrollPane.widthProperty()); //.subtract(10d));
		imageView.fitHeightProperty().unbind();
		setImage(this.image);
	}
	public void fitHeight() {
		imageView.fitWidthProperty().unbind();
		imageView.fitHeightProperty().bind(scrollPane.heightProperty()); //.subtract(10d));
		setImage(this.image);
	}
	public void fitNone() {
		imageView.fitWidthProperty().unbind();
		imageView.fitHeightProperty().unbind();
		setImage(this.image);
	}

	public void zoomIn() {
		zoom += 0.1;
		setImage(this.image);
	}
	public void zoomOut() {
		if( zoom > 0.2 ) { zoom -= 0.1; }
		setImage(this.image);
	}

	public void addMenuItem(ContextMenu menu, String title, Runnable runnable) {
		MenuItem item = new MenuItem();
		item.setText(title);
		item.setOnAction(e -> runnable.run());
		menu.getItems().add(item);
	}
	public void addSeparator(ContextMenu menu) {
		menu.getItems().add(new SeparatorMenuItem());
	}

}

댓글 없음:

댓글 쓰기