I think my question must be confusing. Let me briefly explain, I am using JavaFX, creating a photo editor. I have two controllers and two views. HomeController (from where image view layout is set), and BrightnessController, which opens a new dialogue window, from where I set values of brightness, but when apply changes, it throws error, saying this: enter image description here
This is my HomeController:
package com.example.photoeditor;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Menu;
import javafx.scene.control.MenuBar;
import javafx.scene.control.MenuItem;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.FileChooser;
import javafx.stage.Stage;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
@SuppressWarnings("All")
public class HomeController implements Initializable {
@FXML
Button cropButton;
@FXML
Button brightnessButton;
@FXML
Button contrastButton;
@FXML
Button sharpnessButton;
@FXML
HBox imageViewLayout;
@FXML
ImageView imageView;
@FXML
MenuBar menuBar;
Mat imageMat;
String inputImageFileLocation;
Utilities utilities = new Utilities();
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
// Create two menus
Menu fileMenu = new Menu("File");
// Create some menu items
MenuItem newMenuItem = new MenuItem("New");
MenuItem openMenuItem = new MenuItem("Open");
MenuItem saveMenuItem = new MenuItem("Save");
MenuItem exitMenuItem = new MenuItem("Exit");
// Add menu items to the File menu
fileMenu.getItems().addAll(newMenuItem, openMenuItem, saveMenuItem, exitMenuItem);
// Add menus to the menubar
menuBar.getMenus().addAll(fileMenu);
openMenuItem.setOnAction(new EventHandler<>() {
@Override
public void handle(ActionEvent actionEvent) {
openImage();
}
});
brightnessButton.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
openBrightnessWindow();
}
});
}
// LOADING IMAGE INTO IMAGEVIEW
public void openImage() {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
// Open dialogue to get image location path
FileChooser fileChooser = new FileChooser();
File inputImageFile = fileChooser.showOpenDialog(null);
inputImageFileLocation = inputImageFile.toString().replaceAll(
"\\\\", "\\\\\\\\");
imageMat = Imgcodecs.imread(inputImageFileLocation);
Image image = utilities.mat2Image(imageMat);
setImage(image);
}
public void openBrightnessWindow() {
try {
Parent root = FXMLLoader.load(getClass().getResource("BrightnessView.fxml"));
Scene scene = new Scene(root);
Stage primaryStage = new Stage();
primaryStage.setTitle("Brightness Controller");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.initOwner(brightnessButton.getScene().getWindow());
primaryStage.show();
} catch (Exception e) {
e.printStackTrace();
}
}
public void setImage(Image image) {
imageView.setImage(image);
imageView.fitWidthProperty().bind(imageViewLayout.widthProperty());
imageView.fitHeightProperty().bind(imageViewLayout.heightProperty());
}
}
And this is my BrightnessController:
package com.example.photoeditor;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.TextField;
import javafx.scene.image.Image;
import org.opencv.core.Mat;
import org.opencv.imgcodecs.Imgcodecs;
import java.net.URL;
import java.util.ResourceBundle;
@SuppressWarnings("All")
public class BrightnessController extends HomeController implements Initializable {
@FXML
Button applyChanges;
@FXML
TextField textField;
Utilities utilities = new Utilities();
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
applyChanges.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
enhanceBrightness();
}
});
}
public void enhanceBrightness() {
Mat source = Imgcodecs.imread("D://img.jpg");
Mat destination = new Mat(source.rows(), source.cols(), source.type());
source.convertTo(destination, -1, 10, 50);
Image newImage = utilities.mat2Image(destination);
setImage(newImage);
}
}
I know that some of you will say that I am sending null method (no image) from brightness controller to home controller, well that's not true. When i run the same code in HomeController where Image View layout exists, it works without any problem.
Now this clearly means that JavaFX is having problem with setting images in ImageView from different controllers. This used to be super easy when JavaFX supported to connect multiple views with one controller from fxml files.
Please help me to fix this problem.
Okay so I am inserting this new less complicated version of my program to make it more understandable. I have two controllers, "Controller1.java" and "Controller2.java", they both are connected to scenes, "SceneView1" and "SceneView2". "Controller1.java" has method setImage(Image image) to set an image in image view of "SceneView1". Now I am sending image from "Controller2.java", in other words calling setImage() method, and it is throwing an error.
Controller1:
package com.example.demo;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
import javafx.scene.layout.HBox;
import javafx.stage.Stage;
import java.net.URL;
import java.util.ResourceBundle;
public class Controller1 implements Initializable {
@FXML
Button nextScene;
@FXML
HBox imageViewLayout;
@FXML
ImageView imageView;
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
nextScene.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
try {
Parent root = FXMLLoader.load(getClass().getResource("SceneView2.fxml"));
Scene scene = new Scene(root);
Stage primaryStage = new Stage();
primaryStage.setTitle("Video Library");
primaryStage.setScene(scene);
primaryStage.setResizable(false);
primaryStage.initOwner(nextScene.getScene().getWindow());
primaryStage.show();
} catch (Exception e) {
// PASS
}
}
});
}
public void setImage(Image image) {
imageView.setImage(image);
imageView.fitWidthProperty().bind(imageViewLayout.widthProperty());
imageView.fitHeightProperty().bind(imageViewLayout.heightProperty());
}
}
Controller2:
package com.example.demo;
import javafx.event.ActionEvent;
import javafx.event.EventHandler;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import java.io.ByteArrayInputStream;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.scene.image.Image;
import org.opencv.core.Core;
import org.opencv.core.Mat;
import org.opencv.core.MatOfByte;
import org.opencv.imgcodecs.Imgcodecs;
public class Controller2 implements Initializable {
@FXML
Button addImage;
Controller1 controller1 = new Controller1();
@Override
public void initialize(URL url, ResourceBundle resourceBundle) {
addImage.setOnAction(new EventHandler<ActionEvent>() {
@Override
public void handle(ActionEvent actionEvent) {
System.loadLibrary(Core.NATIVE_LIBRARY_NAME);
Mat imageMat = Imgcodecs.imread("D://img.jpg");
Image image = mat2Image(imageMat);
controller1.setImage(image);
}
});
}
// CONVERTING OPENCV IMAGE TO JAVAFX IMAGE
public Image mat2Image(Mat mat) {
MatOfByte buffer = new MatOfByte();
Imgcodecs.imencode(".png", mat, buffer);
return new Image(new ByteArrayInputStream(buffer.toArray()));
}
}
Here's a print stack trace:
"C:\Program Files\Java\jdk-19\bin\java.exe" -Djava.library.path=D:\Softwares\OpenCV-4.6.0\opencv\build\java\x64 "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\lib\idea_rt.jar=60044:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2021.3.2\bin" -Dfile.encoding=UTF-8 -classpath C:\Users\Administrator\.m2\repository\org\openjfx\javafx-controls\19.0.2.1\javafx-controls-19.0.2.1.jar;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-graphics\19.0.2.1\javafx-graphics-19.0.2.1.jar;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-base\19.0.2.1\javafx-base-19.0.2.1.jar;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-fxml\19.0.2.1\javafx-fxml-19.0.2.1.jar -p "C:\Users\Administrator\.m2\repository\org\openjfx\javafx-controls\19.0.2.1\javafx-controls-19.0.2.1-win.jar;D:\Softwares\OpenCV-4.6.0\opencv\build\java\opencv-460.jar;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-fxml\19.0.2.1\javafx-fxml-19.0.2.1-win.jar;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-graphics\19.0.2.1\javafx-graphics-19.0.2.1-win.jar;D:\Software Engineering\App Development\Desktop Development\Java\Demo\target\classes;C:\Users\Administrator\.m2\repository\org\openjfx\javafx-base\19.0.2.1\javafx-base-19.0.2.1-win.jar" -m com.example.demo/com.example.demo.Main
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.image.ImageView.setImage(javafx.scene.image.Image)" because "this.imageView" is null
at com.example.demo/com.example.demo.Controller1.setImage(Controller1.java:53)
at com.example.demo/com.example.demo.Controller2$1.handle(Controller2.java:35)
at com.example.demo/com.example.demo.Controller2$1.handle(Controller2.java:28)
at javafx.base@19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base@19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
at javafx.base@19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics@19.0.2.1/javafx.scene.Node.fireEvent(Node.java:8923)
at javafx.controls@19.0.2.1/javafx.scene.control.Button.fire(Button.java:203)
at javafx.controls@19.0.2.1/com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:207)
at javafx.controls@19.0.2.1/com.sun.javafx.scene.control.inputmap.InputMap.handle(InputMap.java:274)
at javafx.base@19.0.2.1/com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:247)
at javafx.base@19.0.2.1/com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:234)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at javafx.base@19.0.2.1/com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at javafx.base@19.0.2.1/com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.base@19.0.2.1/javafx.event.Event.fireEvent(Event.java:198)
at javafx.graphics@19.0.2.1/javafx.scene.Scene$MouseHandler.process(Scene.java:3894)
at javafx.graphics@19.0.2.1/javafx.scene.Scene.processMouseEvent(Scene.java:1887)
at javafx.graphics@19.0.2.1/javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2620)
at javafx.graphics@19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:411)
at javafx.graphics@19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:301)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics@19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$2(GlassViewEventHandler.java:450)
at javafx.graphics@19.0.2.1/com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:424)
at javafx.graphics@19.0.2.1/com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:449)
at javafx.graphics@19.0.2.1/com.sun.glass.ui.View.handleMouseEvent(View.java:551)
at javafx.graphics@19.0.2.1/com.sun.glass.ui.View.notifyMouse(View.java:937)
at javafx.graphics@19.0.2.1/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics@19.0.2.1/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:1589)