Using a variable outside of an lambda expression block in JavaFX - java

So, I have a program that loads an image with a FileChooser. I use a lambda expression to define this loading action so the function LoadImage() returns the chosen image inside the event block but I can't use it outside this block.
Can someone help me?
Here is my code so far:
public class Main extends Application{
Stage window;
BorderPane layout;
ImageView imageView;
Image currentImage;
public static void main(String[] args){
launch(args);
}
#Override
public void start(Stage primaryStage) throws Exception{
window = primaryStage;
window.setTitle("Image Viewer v.1.0");
//MENU
Menu fileMenu = new Menu("_File");
MenuItem openFile = new MenuItem("Open file...");
openFile.setOnAction(e -> currentImage = LoadImage());
fileMenu.getItems().add(openFile);
//Main menu bar
MenuBar menuBar = new MenuBar();
menuBar.getMenus().addAll(fileMenu);
imageView = new ImageView();
imageView.setImage(currentImage); //here the currentImage is null
layout = new BorderPane();
layout.setTop(menuBar);
layout.setCenter(imageView);
Scene scene = new Scene(layout, 900, 600);
window.setScene(scene);
window.show();
}
public Image LoadImage()
{
final Image image;
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.JPG)", "*.JPG");
FileChooser.ExtensionFilter extFilterjpg = new FileChooser.ExtensionFilter("jpg files (*.jpg)", "*.jpg");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.PNG)", "*.PNG");
FileChooser.ExtensionFilter extFilterpng = new FileChooser.ExtensionFilter("png files (*.png)", "*.png");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterjpg, extFilterPNG, extFilterpng);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
return new Image(file.toURI().toString());
}
} // end of Main class
So forth, nothing is displayed in the ImageView.
How can I use the value returned by the LoadImage() method?

The value of currentImage is indeed changed, but when you set the value of imageView's image property, it is not yet set. You have to change the property of your ImageView, not the variable (which you use only before setting the image).
Try changing your lambda to:
openFile.setOnAction(e -> imageView.setImage(LoadImage()) )

Related

JavaFX: FileChooser is blinking

It first appears in the left upper corner of the screen and then shows in the middle of the screen.
It is code:
private static File fileChooserDialog( final String initialDirectory, final String initialFileName, final boolean open,
final String filterString, final String... extensions) {
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter = new FileChooser.ExtensionFilter(filterString, extensions);
fileChooser.getExtensionFilters().add(extFilter);
Stage stage = new Stage();
File resultFile;
if(open) {
resultFile = fileChooser.showOpenDialog(stage);
} else {
resultFile = fileChooser.showSaveDialog(stage);
}
if(resultFile != null) {
lastSelectedFilePath = resultFile.getParent();
}
return resultFile;
}
You should not create a new Stage every time you want to show a FileChooser. Remove this line:
Stage stage = new Stage();
And use your application's Window as an owner for the FileChooser. For example, if you are trying to show this dialog when the user clicks a button, you can get the Window like this:
Button button = new Button("Browse");
button.setOnAction(event -> {
Window window = button.getScene().getWindow();
fileChooser.showOpenDialog(window);
event.consume();
});

JavaFX - Tab will not show nor file contents when file is opened

I'm trying to create a text editor using JavaFX. I want to be able to open a file from a window into the main window as a tab. So far, I've created the necessary menu items and an option window that contains the function to open the file explorer to select a file.
When the user presses the "Choose File" button, the file explorer is opened. When a user selects a file, the "Open File" window closes. The main window (3rd image) is then left but does not contain a tab with the file contents.
Upon execution of the "openFile()" function, no errors are returned, but no tab is opened. I believe it may be an issue with trying to open the tab within the "chooseFileButton.SetOnAction()" function but cannot confirm.
Any suggestions/explanations would be much appreciated.
Open File
Open File (FileChooser)
Output:
public class Main extends Application {
public static void main(String[] args) {
launch(args);
}
#Override
public void start(Stage primary) throws Exception {
primary.setTitle("Chris' Text Editor");
MenuBar menuBar = new MenuBar();
VBox vbox = new VBox(menuBar);
/* FILE MENU */
MenuItem openFile = new MenuItem("Open...");
fileMenu.getItems().add(openFile);
Pane rootPane = new Pane();
TextArea editorTextArea = new TextArea();
editorTextArea.setMinHeight(1000);
editorTextArea.setMinWidth(1000);
editorTextArea.setVisible(false);
rootPane.getChildren().add(editorTextArea);
TabPane tabPane = new TabPane();
tabPane.setSide(Side.TOP);
openFile.setOnAction(new EventHandler<ActionEvent>() {
#Override
public void handle(ActionEvent event) {
Label fileLabel = new Label();
fileLabel.setText("No File selected...");
GridPane grid = new GridPane();
Scene contextScene = new Scene(grid, 450, 300);
/* NEW WINDOW */
Stage openFileWindow = new Stage();
openFileWindow.setTitle("Open File");
openFileWindow.setScene(contextScene);
/* SET WINDOW MODAL */
openFileWindow.initModality(Modality.WINDOW_MODAL);
/* SET PARENT WINDOW */
openFileWindow.initOwner(primary);
/* CHOOSE FILE DIRECTORY BUTTON */
openFileWindow.setX(primary.getX() + (primary.getX() / 2));
openFileWindow.setY(primary.getX() + (primary.getX() / 2));
openFileWindow.show();
/* CHOOSE FILE BUTTON */
Button chooseFileButton = new Button();
chooseFileButton.setText("Choose File");
chooseFileButton.setOnAction(new EventHandler<ActionEvent>() {
public void handle(ActionEvent event) {
FileChooser chooseFile = new FileChooser();
File selectedFile = chooseFile.showOpenDialog(openFileWindow);
if(selectedFile != null) {
String filePath = selectedFile.getPath();
fileLabel.setText(filePath);
String fileContent = openFile2(filePath);
/* CREATE NEW TAB */
Tab newTab = new Tab();
newTab.setContent(editorTextArea);
newTab.setText(filePath);
tabPane.getTabs().add(newTab);
editorTextArea.setVisible(true);
/* POPULATE TEXT AREA WITH FILE CONTENTS */
editorTextArea.appendText(fileContent);
/* FOCUS ON TAB */
SingleSelectionModel<Tab> selection = tabPane.getSelectionModel();
selection.select(newTab);
openFileWindow.close();
}
}
});
grid.setAlignment(Pos.CENTER);
grid.setHgap(10);
grid.setVgap(10);
grid.add(chooseFileButton, 0, 0);
grid.add(fileLabel, 0, 1);
}
});
menuBar.getMenus().add(fileMenu);
Scene scene = new Scene(vbox, 1000, 750);
primary.setScene(scene);
primary.show();
}
public String openFile2(String filePath) {
StringBuilder content = new StringBuilder();
try (Stream<String> stream = Files.lines(Paths.get(filePath), StandardCharsets.UTF_8)){
stream.forEach(s -> content.append(s).append("\n"));
} catch (IOException e) {
e.printStackTrace();
}
return content.toString();
}
You never added your TabPane to the scene:
vbox.getChildren().add(tabPane);

How do I display an image using javaFX by selecting a file from file explorer

1.I have a code that opens a pane and I can open file explorer, but I do not know how to open said image when I select it from file explorer. Also this code is meant to be used in different #Overrride statements but I have only managed to get this far using one statement. Is there a way for me to call some of these events from another Override statement?
#Override
public void start(Stage primaryStage) {
//Stage
primaryStage.setTitle("title");
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane);
Button load = new Button("Load");
load.setOnAction(loadEventListener);
ImageView myImageView = new ImageView();
HBox rootBox = new HBox();
rootBox.getChildren().addAll(load, myImageView);
//Toolbar
HBox toolbarArea = new HBox( 10 );
toolbarArea.setPadding( new Insets( 10 ) );
primaryStage.setScene(scene);
primaryStage.show();
//Puts buttons on bottom bar
toolbarArea.getChildren().addAll( load );
pane.setBottom( toolbarArea );
}
EventHandler<ActionEvent> loadEventListener
= t -> {
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
try {
BufferedImage bufferedImage = ImageIO.read(file);
Image image = SwingFXUtils.toFXImage(bufferedImage, null);
ImageView myImageView = new ImageView();
myImageView.setImage(image);
} catch (IOException ex) {
Logger.getLogger(JavaFXPixel.class.getName()).log(Level.SEVERE, null, ex);
}
};
Since you already have an ImageView and have shown it in the scene, simply set its image to the image you load.
For this you need to make the ImageView an instance variable:
private ImageView myImageView ;
#Override
public void start(Stage primaryStage) {
//Stage
primaryStage.setTitle("title");
BorderPane pane = new BorderPane();
Scene scene = new Scene(pane);
Button load = new Button("Load");
load.setOnAction(loadEventListener);
myImageView = new ImageView();
HBox rootBox = new HBox();
rootBox.getChildren().addAll(load, myImageView);
// presumably you intended this somewhere?
pane.setCenter(rootBox);
//Toolbar
HBox toolbarArea = new HBox( 10 );
toolbarArea.setPadding( new Insets( 10 ) );
primaryStage.setScene(scene);
primaryStage.show();
//Puts buttons on bottom bar
toolbarArea.getChildren().addAll( load );
pane.setBottom( toolbarArea );
}
Note there is no need to load a buffered image and then convert it. So all you need in the event handler is
loadEventListener = t -> {
FileChooser fileChooser = new FileChooser();
//Set extension filter
FileChooser.ExtensionFilter extFilterJPG = new FileChooser.ExtensionFilter("JPG files (*.jpg)", "*.JPG");
FileChooser.ExtensionFilter extFilterPNG = new FileChooser.ExtensionFilter("PNG files (*.png)", "*.PNG");
fileChooser.getExtensionFilters().addAll(extFilterJPG, extFilterPNG);
//Show open file dialog
File file = fileChooser.showOpenDialog(null);
if (file != null) {
Image image = new Image(file.toURI().toString());
myImageView.setImage(image);
}
};

JavaFX bulk edit images

I'm trying to edit five images I have in a folder at once (using javafx motion blur), rather than select them one after the other. This is my code, I'm not exactly sure what I'm doing wrong but when I run it, only the last image in the folder gets edited. The others remain as they are.
public class IterateThrough extends Application {
private Desktop desktop = Desktop.getDesktop();
#Override
public void start(Stage primaryStage) throws IOException {
File dir = new File("filepath");
File [] directoryListing = dir.listFiles();
if (directoryListing != null) {
for (File file : directoryListing) {
if(file.getName().toLowerCase().endsWith(".jpeg")){
//desktop.open(file);
Image image = new Image(new FileInputStream(file));
//Setting the image view
ImageView imageView = new ImageView(image);
//setting the fit height and width of the image view
imageView.setFitHeight(600);
imageView.setFitWidth(500);
//Setting the preserve ratio of the image view
imageView.setPreserveRatio(true);
// instantiate Motion Blur class
MotionBlur motionBlur = new MotionBlur();
// set blur radius and blur angle
motionBlur.setRadius(15.0);
motionBlur.setAngle(110.0);
//set imageView effect
imageView.setEffect(motionBlur);
//Creating a Group object
Group root = new Group(imageView);
//Creating a scene object
Scene scene = new Scene(root, 600, 500);
//Setting title to the Stage
primaryStage.setTitle("Loading an image");
//Adding scene to the stage
primaryStage.setScene(scene);
//Displaying the contents of the stage
primaryStage.show();
}
}
}
}
public static void main(String[] args) {
launch(args);
}
}
first, you shouldn't just let the primaryStage show() in the for-each loop, because when the primaryStage first show(), the fx thread pause on that instruction, the remaining pictures will not be read and when you close the window, the loop won't continue to go on for remaining, it represents the end of the application.
so it's better to let the primaryStage show() outside the each-loop after all image has been read.
second, you shouldn't use the "Group" container to contains all images, better use VBox/HBox/FlowPane, make sure above image won't covers below's.
here's modified code for reference.
public class IterateThrough2 extends Application{
private Desktop desktop = Desktop.getDesktop();
#Override
public void start(Stage primaryStage) throws IOException{
File dir = new File("filepath");
File[] directoryListing = dir.listFiles();
FlowPane root = new FlowPane();
if(directoryListing != null){
for(File file : directoryListing){
if(file.getName().toLowerCase().endsWith(".jpeg")){
Image image = new Image(new FileInputStream(file));
ImageView imageView = new ImageView(image);
imageView.setFitHeight(600);
imageView.setFitWidth(500);
imageView.setPreserveRatio(true);
MotionBlur motionBlur = new MotionBlur();
motionBlur.setRadius(15.0);
motionBlur.setAngle(110.0);
imageView.setEffect(motionBlur);
root.getChildren().add(imageView);
}
}
}
Scene scene = new Scene(root, 600, 500);
primaryStage.setTitle("Loading an image");
primaryStage.setScene(scene);
primaryStage.show();
}
public static void main(String[] args){
launch(args);
}
}

Adding frame to picture in Javafx

i would like to add a frame to a picture using Java and Javafx and then save the framed picture. What would be the best way to do that?
For example say I have a photo of a landscape and want to add a frame to it. The framed photo should look like this:
You could add two images, first the frame, then the image, to the same canvas like this:
GraphicsContext gc1 = canvas.getGraphicsContext2D();
gc1.drawImage(frameimage,0,0,image.getFitWidth()+20,image.getFitHeight()+20);
GraphicsContext gc = canvas.getGraphicsContext2D();
gc.drawImage(i,10,10,image.getFitWidth(),image.getFitHeight());
and then save them as png (or whatever format you like) using the canvas.snapshot function:
FileChooser fileChooser = new FileChooser();
FileChooser.ExtensionFilter extFilter =new FileChooser.ExtensionFilter("png files (*.png)", "*.png");
fileChooser.getExtensionFilters().add(extFilter);
Stage primaryStage = (Stage) canvas.getScene().getWindow();
File file = fileChooser.showSaveDialog(primaryStage);
if(file != null){
try {
WritableImage writableImage = new WritableImage((int)canvas.getWidth(), (int)canvas.getHeight());
canvas.snapshot(null, writableImage);
RenderedImage renderedImage = SwingFXUtils.fromFXImage(writableImage, null);
File file1 = new File(file.getAbsolutePath()+".png");
file.renameTo(file1);
ImageIO.write(renderedImage, "png", file1);
} catch (IOException ex) {
ex.printStackTrace();
}

Categories

Resources