From 3c6870074db378240192af3eff872142cfe29483 Mon Sep 17 00:00:00 2001 From: _N0x Date: Fri, 12 Feb 2021 23:38:01 +0100 Subject: [PATCH] Added basic functionality for opening files, zooming, full-screen, switching through images --- src/de/thm/tlf/photoViewer/Controller.java | 320 ++++++++++++------ .../NoPicturesLoadedException.java | 7 + .../thm/tlf/photoViewer/PictureHandler.java | 47 ++- .../tlf/photoViewer/{ => data}/Picture.java | 2 +- .../{ => data}/PicturePreview.java | 4 +- 5 files changed, 261 insertions(+), 119 deletions(-) create mode 100644 src/de/thm/tlf/photoViewer/NoPicturesLoadedException.java rename src/de/thm/tlf/photoViewer/{ => data}/Picture.java (92%) rename src/de/thm/tlf/photoViewer/{ => data}/PicturePreview.java (65%) diff --git a/src/de/thm/tlf/photoViewer/Controller.java b/src/de/thm/tlf/photoViewer/Controller.java index 13afd2e..8e288d3 100644 --- a/src/de/thm/tlf/photoViewer/Controller.java +++ b/src/de/thm/tlf/photoViewer/Controller.java @@ -1,6 +1,11 @@ package de.thm.tlf.photoViewer; +import de.thm.tlf.photoViewer.data.PicturePreview; import javafx.application.Application; +import javafx.beans.property.DoubleProperty; +import javafx.beans.property.SimpleDoubleProperty; +//import javafx.beans.value.ChangeListener; +///import javafx.beans.value.ObservableValue; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.geometry.Insets; @@ -8,20 +13,62 @@ import javafx.geometry.Pos; import javafx.scene.Node; import javafx.scene.Scene; import javafx.scene.control.*; -import javafx.scene.image.Image; import javafx.scene.image.ImageView; import javafx.scene.layout.*; +import javafx.stage.FileChooser; import javafx.stage.Stage; +import java.io.File; +import java.util.List; + /** * Controller Class for Image-viewer. - * Holds controls for the GUI elements. + * Holds GUI elements * * @author Tim Lukas Förster + * @version 0.1 */ + public class Controller extends Application { - private PictureHandler picHandler = new PictureHandler(); + // CENTER // + private final DoubleProperty zoomProperty = new SimpleDoubleProperty(200); + private final ScrollPane currentViewSP = new ScrollPane(); + private final ImageView centerImageView = new ImageView(); + + // LEFT // + private final VBox leftPane = new VBox(); + private final VBox selectionPane = new VBox(); + private final ScrollPane pictureSelector = new ScrollPane(); + + // TOP // + private final VBox menu = new VBox(); + private final MenuBar menuBar = new MenuBar(); + private final Menu fileMenu = new Menu("File"); + private final Menu aboutMenu = new Menu("About"); + private final MenuItem openFiles = new MenuItem("Open"); + private final MenuItem startSlideShow = new MenuItem("Start Slide Show"); + private final MenuItem exitViewer = new Menu("Exit"); + private final MenuItem showInfo = new Menu("Information"); + + // BOTTOM // + private final BorderPane bottomPanel = new BorderPane(); + private final HBox bottomLeft = new HBox(); + private final HBox bottomMid = new HBox(); + private final HBox bottomRight = new HBox(); + + private Slider zoomSlider; + private final Button openFilesButton = new Button("Open Pictures"); + + private final Button prevPicBtn = new Button("<-"); + private final Button nextPicBtn = new Button("->"); + private final Button slideShowBtn = new Button("Slide Show"); + + private final Button fullScreenBtn = new Button("Fullscreen"); + + // Picture handling // + private PictureHandler picHandler; + public static void main(String[] args) { launch(args); @@ -29,105 +76,121 @@ public class Controller extends Application { @Override public void start(Stage primaryStage) { - /* ############################## - * #### MAIN PANE #### - * #############################*/ - BorderPane mainPane = new BorderPane(); - // #### END MAIN PANE #### + picHandler = new PictureHandler(); + BorderPane root = new BorderPane(); + root.setLeft(createLeft()); + root.setCenter(createCenter()); + root.setTop(createTop()); + root.setBottom(createBottom()); + Scene mainScene = new Scene(root, 1200, 800); - /* ############################## - * #### BOTTOM PANEL #### - * #############################*/ - BorderPane bottom = new BorderPane(); - bottom.setPadding(new Insets(5,5,5,5)); - - // ZoomSlider -> Bottom Left - HBox bottomLeft = new HBox(); - Slider zoomSlider = new Slider(0, 100, 15); - zoomSlider.setShowTickMarks(true); - // Open Button - Button openFilesButton = new Button("Open Pictures"); - - bottomLeft.getChildren().addAll(openFilesButton, zoomSlider); - bottom.setLeft(bottomLeft); - - HBox bottomMid = new HBox(); - bottomMid.setAlignment(Pos.CENTER); - bottomMid.setSpacing(5); - Button prevPicBtn = new Button("<-"); - Button nextPicBtn = new Button("->"); - Button diashowBtn = new Button("Diashow"); - bottomMid.getChildren().addAll(prevPicBtn, diashowBtn, nextPicBtn); - bottom.setCenter(bottomMid); - - HBox bottomRight = new HBox(); - Button fullScreenBtn = new Button("Fullscreen"); - bottomRight.getChildren().add(fullScreenBtn); - bottom.setRight(bottomRight); - - //Button Actions - prevPicBtn.setOnAction(new EventHandler() { - @Override public void handle(ActionEvent e) { - picHandler.nextPicture(); + //// Keypress Actions //// + mainScene.setOnKeyPressed(event -> { + switch (event.getCode()) { + case RIGHT: + try{ + centerImageView.setImage(picHandler.getPrevPicture().getImage()); + } + catch (NoPicturesLoadedException npl){ npl.printStackTrace();} + break; + case LEFT: + try{ + centerImageView.setImage(picHandler.getNextPicture().getImage()); + } + catch (NoPicturesLoadedException npl){ npl.printStackTrace();} + break; } }); - mainPane.setBottom(bottom); - // #### END BOTTOM PANEL #### + //// End Keypress Actions //// + + //// Center Zoom Action //// + zoomProperty.addListener(observable -> { + centerImageView.setFitWidth(zoomProperty.get()); + centerImageView.setFitHeight(zoomProperty.get()); + //centerImageView.setFitWidth(zoomProperty.get() * 4); + //centerImageView.setFitHeight(zoomProperty.get() * 3); + }); + + zoomSlider.valueProperty().addListener((observableValue, oldVal, newVal) -> { + if (oldVal.doubleValue() < newVal.doubleValue()){ + zoomProperty.set(zoomProperty.get() + 10); + } + else if (oldVal.doubleValue() > newVal.doubleValue()){ + zoomProperty.set(zoomProperty.get() - 10); + } + }); + + /* Currently not used. A method that allow scrolling with the mouse wheel when inside the center + currentViewSP.addEventFilter(ScrollEvent.ANY, scrollEvent -> { + + if (scrollEvent.getDeltaY() > 0) { + zoomProperty.set(zoomProperty.get() * 1.1); + } else if (scrollEvent.getDeltaY() < 0) { + zoomProperty.set(zoomProperty.get() / 1.1); + } + }); + /**/ + //// End Center Zoom Action //// + + //// Menu Actions //// + openFiles.setOnAction(openFileDialog(primaryStage)); + //// End Menu Actions //// - /* ############################## - * #### TOP PANEL #### - * #############################*/ - VBox menu = new VBox(); - // File Menu - Menu fileMenu = new Menu("File"); - MenuItem openFiles = new MenuItem("Open"); - MenuItem startDiashow = new MenuItem("Start Diashow"); - MenuItem exitViewer = new Menu("Exit"); - SeparatorMenuItem sep = new SeparatorMenuItem(); - fileMenu.getItems().addAll(openFiles, sep, startDiashow, exitViewer); - // About Menu - Menu aboutMenu = new Menu("About"); - MenuItem showInfo = new Menu("Information"); - aboutMenu.getItems().addAll(showInfo); - // Menu bare - MenuBar menuBar = new MenuBar(); - menuBar.getMenus().addAll(fileMenu, aboutMenu); - // Adding Menus to Top Panel - menu.getChildren().addAll(menuBar); - mainPane.setTop(menu); - // #### END TOP PANEL #### + //// Button Actions //// + openFilesButton.setOnAction(openFileDialog(primaryStage)); + prevPicBtn.setOnAction(e -> { + try{ + centerImageView.setImage(picHandler.getPrevPicture().getImage()); + } + catch (NoPicturesLoadedException npl){ npl.printStackTrace();} + }); - /* ############################## - * #### CENTER PANEL #### - * #############################*/ - Picture testPic = new Picture("pic/image3.jpg"); - ScrollPane currentViewSP = new ScrollPane(); - Image image = testPic.getImage(); - //Creating the image view - ImageView imageView = new ImageView(); - //Setting image to the image view - imageView.setImage(image); - //Setting the image view parameters - imageView.setX(10); - imageView.setY(10); - imageView.setPreserveRatio(true); - currentViewSP.setContent(imageView); - mainPane.setCenter(currentViewSP); - // #### END CENTER PANEL #### + nextPicBtn.setOnAction(e -> { + try{ + centerImageView.setImage(picHandler.getNextPicture().getImage()); + } + catch (NoPicturesLoadedException npl){ npl.printStackTrace();} + }); + fullScreenBtn.setOnAction(e -> primaryStage.setFullScreen(true)); + //// End Button Actions //// - /* ############################## - * #### LEFT PANEL #### - * #############################*/ - VBox leftPane = new VBox(); - VBox selectionPane = new VBox(); - selectionPane.setPadding(new Insets(5,5,5,5)); - selectionPane.setSpacing(5); + primaryStage.setTitle("Photo Viewer"); + primaryStage.setScene(mainScene); + primaryStage.show(); + } - // Add all previews to the + /** + * Open file-dialog allowing to select multiple pictures (via filter), + * adds them to the PictureHandler and updates the picture preview + * @param stage the primary stage, used to display the file-open-dialog + * @return EventHandler for dialog handling + */ + private EventHandler openFileDialog(Stage stage) { + return e -> { + FileChooser fileChooser = new FileChooser(); + fileChooser.setTitle("Open Pictures"); + fileChooser.getExtensionFilters().addAll( + new FileChooser.ExtensionFilter("Image Files", "*.png", "*.jpg", "*.gif")); + List selectedPictures = fileChooser.showOpenMultipleDialog(stage); + if (selectedPictures != null) { + try{ + picHandler.loadPictures(selectedPictures); + Controller.this.updatePreviewView(); + centerImageView.setImage(picHandler.getNextPicture().getImage()); + } + catch (NoPicturesLoadedException npl){ npl.printStackTrace();} + } + }; + } + + /** + * + */ + private void updatePreviewView(){ for(PicturePreview pp: picHandler.getPreviews()){ ImageView iv = new ImageView(pp.getImage()); iv.setFitWidth(150); @@ -135,16 +198,71 @@ public class Controller extends Application { iv.setPreserveRatio(true); selectionPane.getChildren().add(iv); } - ScrollPane pictureSelector = new ScrollPane(); - pictureSelector.setContent(selectionPane); - - leftPane.getChildren().addAll(pictureSelector); - mainPane.setLeft(leftPane); - // #### END LEFT PANEL #### - - primaryStage.setTitle("Photo Viewer"); - primaryStage.setScene(new Scene(mainPane, 1200, 600)); - primaryStage.show(); } + /** + * Method that handles the settings and layout of the Left Panel + * @return Node, set up for displaying on the left of a GridPane + */ + private Node createLeft(){ + selectionPane.setPadding(new Insets(5,5,5,5)); + selectionPane.setSpacing(5); + pictureSelector.setContent(selectionPane); + leftPane.getChildren().addAll(pictureSelector); + return leftPane; + } + + /** + * Method that handles the settings and layout of the top Panel + * @return Node, set up for displaying on the top of a GridPane + */ + private Node createTop(){ + SeparatorMenuItem sep = new SeparatorMenuItem(); + fileMenu.getItems().addAll(openFiles, sep, startSlideShow, exitViewer); + // About Menu + + aboutMenu.getItems().addAll(showInfo); + // Menu bare + menuBar.getMenus().addAll(fileMenu, aboutMenu); + // Adding Menus to Top Panel + menu.getChildren().addAll(menuBar); + return menu; + } + + /** + * Method that handles the settings and layout of the center Panel + * @return Node, set up for displaying on the center of a GridPane + */ + private Node createCenter(){ + centerImageView.setX(10); + centerImageView.setY(10); + centerImageView.setPreserveRatio(true); + currentViewSP.setContent(centerImageView); + return currentViewSP; + } + + /** + * Method that handles the settings and layout of the bottom Panel + * @return Node, set up for displaying on the bottom of a GridPane + */ + private Node createBottom() { + bottomPanel.setPadding(new Insets(5, 5, 5, 5)); + + // Left Bottom Part + zoomSlider = new Slider(0, 100, 25); + zoomSlider.setShowTickMarks(true); + bottomLeft.getChildren().addAll(openFilesButton, zoomSlider); + bottomPanel.setLeft(bottomLeft); + + // Middle Bottom Part + bottomMid.setAlignment(Pos.CENTER); + bottomMid.setSpacing(5); + bottomMid.getChildren().addAll(prevPicBtn, slideShowBtn, nextPicBtn); + bottomPanel.setCenter(bottomMid); + + // Right Bottom Part + bottomRight.getChildren().add(fullScreenBtn); + bottomPanel.setRight(bottomRight); + return (bottomPanel); + } } diff --git a/src/de/thm/tlf/photoViewer/NoPicturesLoadedException.java b/src/de/thm/tlf/photoViewer/NoPicturesLoadedException.java new file mode 100644 index 0000000..0972fbd --- /dev/null +++ b/src/de/thm/tlf/photoViewer/NoPicturesLoadedException.java @@ -0,0 +1,7 @@ +package de.thm.tlf.photoViewer; + +public class NoPicturesLoadedException extends Exception{ + NoPicturesLoadedException(String s){ + super(s); + } +} \ No newline at end of file diff --git a/src/de/thm/tlf/photoViewer/PictureHandler.java b/src/de/thm/tlf/photoViewer/PictureHandler.java index 12f1604..5d93181 100644 --- a/src/de/thm/tlf/photoViewer/PictureHandler.java +++ b/src/de/thm/tlf/photoViewer/PictureHandler.java @@ -1,29 +1,48 @@ package de.thm.tlf.photoViewer; +import de.thm.tlf.photoViewer.data.Picture; +import de.thm.tlf.photoViewer.data.PicturePreview; + +import java.io.File; +import java.util.*; + public class PictureHandler { - private PicturePreview[] previews = new PicturePreview[]{ - new PicturePreview("pic/image1.jpg"), - new PicturePreview("pic/image2.jpg"), - new PicturePreview("pic/image3.jpg") - }; + private ArrayList pictures = new ArrayList<>(); + private ArrayList previews = new ArrayList<>(); - private int currentPictureID = 0; + private int currentPictureID = -1; - public PicturePreview[] getPreviews(){ + public ArrayList getPreviews(){ return previews; } - public void loadPictures(){ - + public void loadPictures(List pictureFiles){ + for(File picFile : pictureFiles){ + pictures.add(new Picture(picFile.getPath())); + previews.add(new PicturePreview(picFile.getPath())); + } } - public Picture nextPicture(){ - return null; + public Picture getNextPicture() throws NoPicturesLoadedException { + if(pictures.size() <= 0){ + throw new NoPicturesLoadedException("No pictures have been loaded"); + } + else { + currentPictureID = (currentPictureID + 1) % pictures.size(); + return pictures.get(currentPictureID); + } } - public Picture prevPicture(){ - return null; - } + public Picture getPrevPicture() throws NoPicturesLoadedException{ + if(pictures.size() <= 0){ + throw new NoPicturesLoadedException("No pictures have been loaded"); + } + else { + currentPictureID = (currentPictureID + pictures.size() - 1) % pictures.size(); + return pictures.get(currentPictureID); + } + } } + diff --git a/src/de/thm/tlf/photoViewer/Picture.java b/src/de/thm/tlf/photoViewer/data/Picture.java similarity index 92% rename from src/de/thm/tlf/photoViewer/Picture.java rename to src/de/thm/tlf/photoViewer/data/Picture.java index 99ad329..26f9cbf 100644 --- a/src/de/thm/tlf/photoViewer/Picture.java +++ b/src/de/thm/tlf/photoViewer/data/Picture.java @@ -1,4 +1,4 @@ -package de.thm.tlf.photoViewer; +package de.thm.tlf.photoViewer.data; import javafx.scene.image.Image; diff --git a/src/de/thm/tlf/photoViewer/PicturePreview.java b/src/de/thm/tlf/photoViewer/data/PicturePreview.java similarity index 65% rename from src/de/thm/tlf/photoViewer/PicturePreview.java rename to src/de/thm/tlf/photoViewer/data/PicturePreview.java index 3211b90..d49cbf8 100644 --- a/src/de/thm/tlf/photoViewer/PicturePreview.java +++ b/src/de/thm/tlf/photoViewer/data/PicturePreview.java @@ -1,6 +1,4 @@ -package de.thm.tlf.photoViewer; - -import java.io.FileInputStream; +package de.thm.tlf.photoViewer.data; public class PicturePreview extends Picture{