0

I'm in a college, learning Java and one of our projects has asked us to make an image editor (whose controller is called ImageDisplayController) that has a kernel filter window after a button is pressed (lovingly labeled "Show Filter"). This is done through 2 separate stages, as suggested by my instructors.

However, in trying to get the image in an ImageView (called imageView2, it keeps returning as a null. I've created an instance of the controller, called mainController, and gotten imageView2 from there, and then used the getImage() method to get the image in the ImageView, however it still returns as null. Can someone please show me what I'm doing wrong? Any help is appreciated.

private void applyKernel() {
        try {
            double sum = 0;
            for (int j = 0; j < 9; j++) {
                sum += Double.parseDouble(textFields()[j]);
            }
            for (int i = 0; i < 9; i++) {
                double textNum = Double.parseDouble(textFields()[i]);
                textNum /= sum;
                kernel[i] = textNum;
            }

            //Part Where There's Trouble

            FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("ImageDisplay.fxml"));
            ImageDisplayController mainController = fxmlLoader.getController();
            Image image = mainController.imageView2.getImage();
            Image newImage = convolve(image, kernel);
            mainController.imageView2.setImage(newImage);
        } catch (NumberFormatException e) {
            System.out.println("That is not a valid number");
        } catch (NullPointerException e) {
            System.err.println("The image cannot be null");
        }
    }
  • You don't actually load the FXML file, so the `mainController` will be null. There's not much point in creating an `FXMLLoader` if you don't parse and load the FXML file, and display the GUI you load from it... Can you explain more clearly what you're doing here? – James_D Feb 22 '20 at 01:11
  • The bottom line is that you should use a shared model to communicate between controllers. Maybe see if [this](https://stackoverflow.com/questions/32342864/applying-mvc-with-javafx/32343342#32343342) helps. But there's not really enough information in the question here to understand what you're trying to do. – James_D Feb 22 '20 at 01:16
  • Of course. I have two windows, one for displaying the image, another for adding a kernel filter to it. The first window is controlled by `ImageDisplayController`, the second is controlled by `KernelDisplayController`. This code is in `KernelDisplayController`. In it, I am trying to load an image from the ImageView, `imageView2`, located in `ImageDisplayController`. After that, I apply a kernel filter to it with a separate method called `convolve()`, and then I set `imageView2` to display the newly altered image. I'm just trying to get access to `imageView2` from `ImageDisplayController`. – Hashbrown565 Feb 22 '20 at 01:18
  • Which `ImageDisplayController`? Maybe sounds like you have (or think you have) two instances? But again, the `loader` in the code (you call it `fxmlLoader`) from which you are trying to retrieve the controller hasn't even read the FXML file (never mind displayed its contents on the screen), so its controller will be null. – James_D Feb 22 '20 at 01:20
  • I'm sorry, I don't understand your question about which `ImageDisplayController` I'm referring to. – Hashbrown565 Feb 22 '20 at 01:24
  • Please don't be patronized by this question if it seems trivial; I don't know how much Java you know, and I'm just trying to gauge how to explain why I don't understand your code. Do you fully understand the difference between a class and an object? – James_D Feb 22 '20 at 01:25
  • It's no problem. I believe I do understand the difference between an object and a class. – Hashbrown565 Feb 22 '20 at 01:29
  • OK, good. So `ImageDisplayController` is a *class*. Each `FXMLLoader` instance (object) has a property called its controller, which is an *object* whose type (class) is determined by the `fx:controller` attribute in the FXML file. Each `FXMLLoader`'s controller is initialized when it loads the FXML file. Here (1): you create an `FXMLLoader`, but never load the FXML file from it, so `fxmlLoader.getController()` will return null. But also (2) even if you did call `load()`, the *object* you get would be a different object from the one you want, because (I assume) you load that file elsewhere. – James_D Feb 22 '20 at 01:32
  • The conclusion, of course, is that the other place in your code where you actually do load the `ImageDisplay.fxml` file is the place where you need to get a reference to the controller, and you need to somehow arrange to pass that reference to this method (or have some other mechanism for accessing the image from it; the preferred one being sharing a data model between the different controllers). – James_D Feb 22 '20 at 01:36
  • 1
    We crossed comments, but I can't give a complete answer without knowing more of your code. I guess my suggestion would be to create the smallest possible example you can think of where you need to access one controller from another, and see if you can get it to work. If you can't you can either edit this question or post a new one with the complete example in it. But also see my previous link, and [this (famous) question](https://stackoverflow.com/questions/14187963/passing-parameters-javafx-fxml) to see if that gives you ideas. – James_D Feb 22 '20 at 01:39
  • 1
    I think I see what you're saying. In order to obtain `imageView2` and its accompanied data, I need to go into the class where I actually load `ImageDisplay.fxml` and create a reference for `ImageDisplayController`, then I need to pass that reference into the new controller. Afterwards, I'll just call `imageView2` via `mainController.imageView2`. Am I understanding what you're saying? Do feel free to say I'm not, I only want to learn. Apologies for any perceived lack of understanding of Java, by the way. – Hashbrown565 Feb 22 '20 at 01:42
  • You stated the plan for fixing this perfectly. Go see if you can make it work. And this is exactly how you learn, so you shouldn't apologize. – James_D Feb 22 '20 at 01:43
  • See [this](https://stackoverflow.com/a/55675209/3992939) example of two controllers sharing one model. – c0der Feb 22 '20 at 06:37

0 Answers0