1

I have a class called "AdjustmentBar" that includes an imageView, a menubar and some picture editing functions (a FXML file and a controller). AdjustmentBar is loaded to another class called "ExaminationDisplayer" (also a FXML file and a controller). ExaminationDisplayer loads a few images from an online MySQL database, and I want each of these images to be displayed in a seperate imageView.

I have been able to load the AdjustmentBar into the ExaminationDisplayer, but I can't figure out how to setImage() of the imageView that is included in AdjustmentBar. I can display an image from the database in a imageview that I make specifically in the ExaminationDisplayer, and I can display a picture in the AdjustmentBar-view if I run that one seperately. I just can't get the loaded AdjustmentBar to display the image in ExaminationDisplayer.

When I run it I get a nullpointerexception error for this line of code: imgView.setImage(image), which is in the ExaminationDisplayerController:

public class ExaminationDisplayerController extends AdjustmentBarController {
    @FXML
    private void handlebtnFraminghamAction(ActionEvent event) throws IOException {showCardiacConditionEstimator(); }
    @FXML
    private AnchorPane anchorPane; 
    @FXML
    private LineChart<Number, Number> lcChart;
    @FXML
    private NumberAxis xAxis; // x-Axis is defined
    @FXML
    private NumberAxis yAxis; //y-Axis is defined

    public void initialize() throws ClassNotFoundException, SQLException, IOException { // Loading methods in ExaminationDisplayerController
        SPECTLoad();
    }

    public void showCardiacConditionEstimator() throws IOException { // Method for displaying CardiacConditionEstimator
        Parent parent = FXMLLoader.load(getClass().getResource("/fxml/CardiacConditionEstimator.fxml")); //Reference to the fxml file
        Stage stage = new Stage(); // creating a new stage 
        Scene scene = new Scene(parent); // creating a new scene for the file to be shown onto
        stage.setScene(scene); // sets the scene on the stage
        stage.show(); // Displaying the stage 
        stage.setMaximized(false); // maximizing the stage
    }

    public void SPECTLoad() throws SQLException, ClassNotFoundException {
        DBConnection dbConn = new DBConnection(); 
        Connection conn = dbConn.connect(); 
        PreparedStatement pstmt = null;

        try {

            for (int numberOfExaminations = 0; numberOfExaminations < 3; numberOfExaminations++) {

                String[] ID = {"1111", "1112", "1113"};
                List<String> chosenExaminations = Arrays.asList(ID);
                String SQL = "SELECT `IMAGE` FROM `SPECT` WHERE `ID` = ?;";
                pstmt = conn.prepareStatement(SQL);

                pstmt.setString(1, chosenExaminations.get(numberOfExaminations));

                ResultSet rs = pstmt.executeQuery();

                while (rs.next()) {
                    InputStream is = rs.getBinaryStream("IMAGE");
                    OutputStream os = new FileOutputStream(new File("SPECT_IMAGE.jpg"));

                    byte[] content = new byte[1024];
                    int size = 0;
                    while ((size = is.read(content)) != -1) { // Når inputstream er real passer den et -1 værdi og så stoppes loopet
                        os.write(content, 0, size);
                    }
                    os.close();
                    is.close();

                    Image image = new Image(new File("SPECT_IMAGE.jpg").toURI().toString(), 200, 200, true, true);

                    anchorPane.getChildren().add(FXMLLoader.load(getClass().getResource("/fxml/AdjustmentBar.fxml")));
                    imgView.setImage(image);
                }
            }

//}
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

Here is the code for AdjustmentBarController:

public class AdjustmentBarController {

    @FXML
    private AnchorPane AnchorPane;
    @FXML
    private ScrollPane ScrollPane;
    @FXML
    public ImageView imgView;
    @FXML
    private Slider contrastAdjuster;
    @FXML
    private ToggleButton btnMeasure;
    @FXML
    private Pane imgContainer;
    @FXML
    private Label txtLabel;

    @FXML
    private void btnZoomInAction(ActionEvent event) {...}

    @FXML
    private void btnZoomOutAction(ActionEvent event) {...}

    @FXML
    private void btnRotateRightAction(ActionEvent event) {...}

    @FXML
    private void btnRotateLeftAction(ActionEvent event) {...}

    /**
     * Initializes the controller class.
     *
     * @param url
     * @param rb
     */
    public void initialize(URL url, ResourceBundle rb
    ) {
        contrastAdjuster.valueProperty().addListener((observable, oldValue, newValue) -> {
            double value = contrastAdjuster.getValue();
            ColorAdjust colorAdjust = new ColorAdjust();
            colorAdjust.setContrast(value);
            imgView.setEffect(colorAdjust);
        });
    }
}

I'm not sure if the FXML file for AdjustmentBar is relevant, but here goes:

<?xml version="1.0" encoding="UTF-8"?>

<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ScrollPane?>
<?import javafx.scene.control.Slider?>
<?import javafx.scene.control.ToggleButton?>
<?import javafx.scene.image.Image?>
<?import javafx.scene.image.ImageView?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>

<AnchorPane id="AnchorPane" prefHeight="435.0" prefWidth="435.0" xmlns="http://javafx.com/javafx/8.0.111" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Multimodality.controller.AdjustmentBarController">
    <children>
      <BorderPane prefHeight="435.0" prefWidth="435.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
         <center>
            <ScrollPane fx:id="ScrollPane" pannable="true" prefHeight="435.0" prefWidth="435.0" BorderPane.alignment="CENTER">
               <content>
                  <Pane fx:id="imgContainer">
                     <children>
                          <ImageView fx:id="imgView" fitHeight="400.0" fitWidth="400.0" nodeOrientation="INHERIT" pickOnBounds="true" preserveRatio="true" />
                        <Label fx:id="txtLabel" alignment="TOP_LEFT" layoutX="336.0" layoutY="-1.0" prefHeight="134.0" prefWidth="75.0" wrapText="true" />
                     </children>
                  </Pane>
               </content>
            </ScrollPane>
         </center>
         <bottom>
            <HBox alignment="CENTER" prefHeight="35.0" prefWidth="435.0" spacing="8.0" BorderPane.alignment="CENTER">
               <children>
                      <Button fx:id="btnZoomOut" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnZoomOutAction" prefHeight="25.0" prefWidth="25.0">
                          <graphic>
                              <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                                  <image>
                                      <Image url="/img/icon_zoomout.png" />
                                  </image>
                              </ImageView>
                          </graphic>
                      </Button>
                      <Button fx:id="btnZoom100" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnZoom100Action" prefHeight="25.0" prefWidth="25.0">
                          <graphic>
                              <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                                  <image>
                                      <Image url="/img/icon_fit.png" />
                                  </image>
                              </ImageView>
                          </graphic>
                      </Button>
                      <Button fx:id="btnZoomIn" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnZoomInAction" prefHeight="25.0" prefWidth="25.0">
                          <graphic>
                              <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                                  <image>
                                      <Image url="/img/icon_zoomin.png" />
                                  </image>
                              </ImageView>
                          </graphic>
                      </Button>
                      <Button fx:id="btnRotateRight" contentDisplay="CENTER" graphicTextGap="0.0" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnRotateRightAction" prefHeight="25.0" prefWidth="25.0">
                          <graphic>
                              <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                                  <image>
                                      <Image url="/img/shape_rotate_clockwise.png" />
                                  </image>
                              </ImageView>
                          </graphic>
                      </Button>      
                      <Button fx:id="btnRotateLeft" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnRotateLeftAction" prefHeight="25.0" prefWidth="25.0">
                          <graphic>
                              <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                                  <image>
                                      <Image url="/img/shape_rotate_anticlockwise.png" />
                                  </image>
                              </ImageView>
                          </graphic>
                      </Button>
                  <ToggleButton fx:id="btnMeasure" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" mnemonicParsing="false" onAction="#btnMeasureAction" prefHeight="25.0" prefWidth="25.0">
                     <graphic>
                        <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                            <image>
                                <Image url="/img/ruler.png" />
                            </image>
                        </ImageView>
                     </graphic>
                  </ToggleButton>
                  <ImageView fitHeight="20.0" fitWidth="20.0" preserveRatio="true">
                     <image>
                        <Image url="/img/contrast.png" />
                     </image>
                     <HBox.margin>
                        <Insets left="8.0" right="-2.0" />
                     </HBox.margin>
                  </ImageView>
                      <Slider fx:id="contrastAdjuster" blockIncrement="0.1" majorTickUnit="0.5" max="1.0" min="-1.0" minorTickCount="4" prefHeight="24.0" prefWidth="128.0" showTickMarks="true" />
               </children>
               <BorderPane.margin>
                  <Insets />
               </BorderPane.margin>
            </HBox>
         </bottom>
      </BorderPane>
    </children>
</AnchorPane>

Last but no least, here is the nullPointerException I get if I run the code:

java.lang.NullPointerException
    at Multimodality.controller.ExaminationDisplayerController.SPECTLoad(ExaminationDisplayerController.java:224)
    at Multimodality.controller.ExaminationDisplayerController.initialize(ExaminationDisplayerController.java:86)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2566)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
    at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
    at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
    at Multimodality.controller.ExaminationOverviewController.showExaminationDisplayer(ExaminationOverviewController.java:352)
    at Multimodality.controller.ExaminationOverviewController.btnChooseExaminationsAction(ExaminationOverviewController.java:341)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.Trampoline.invoke(MethodUtil.java:71)
    at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.lang.reflect.Method.invoke(Method.java:498)
    at sun.reflect.misc.MethodUtil.invoke(MethodUtil.java:275)
    at javafx.fxml.FXMLLoader$MethodHandler.invoke(FXMLLoader.java:1769)
    at javafx.fxml.FXMLLoader$ControllerMethodEventHandler.handle(FXMLLoader.java:1657)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:86)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:49)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Node.fireEvent(Node.java:8413)
    at javafx.scene.control.Button.fire(Button.java:185)
    at com.sun.javafx.scene.control.behavior.ButtonBehavior.mouseReleased(ButtonBehavior.java:182)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:96)
    at com.sun.javafx.scene.control.skin.BehaviorSkinBase$1.handle(BehaviorSkinBase.java:89)
    at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
    at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
    at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
    at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
    at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
    at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
    at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
    at javafx.event.Event.fireEvent(Event.java:198)
    at javafx.scene.Scene$MouseHandler.process(Scene.java:3757)
    at javafx.scene.Scene$MouseHandler.access$1500(Scene.java:3485)
    at javafx.scene.Scene.impl_processMouseEvent(Scene.java:1762)
    at javafx.scene.Scene$ScenePeerListener.mouseEvent(Scene.java:2494)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:381)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler$MouseEventNotification.run(GlassViewEventHandler.java:295)
    at java.security.AccessController.doPrivileged(Native Method)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleMouseEvent$354(GlassViewEventHandler.java:417)
    at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
    at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleMouseEvent(GlassViewEventHandler.java:416)
    at com.sun.glass.ui.View.handleMouseEvent(View.java:555)
    at com.sun.glass.ui.View.notifyMouse(View.java:937)
    at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
    at com.sun.glass.ui.win.WinApplication.lambda$null$148(WinApplication.java:191)
    at java.lang.Thread.run(Thread.java:745)

BUILD SUCCESSFUL

Total time: 52.909 secs

I hope some of you can help me! Thank you in advance :-)

ItachiUchiha
  • 36,135
  • 10
  • 122
  • 176
Heidi
  • 71
  • 1
  • 9
  • Two statements confuse me - "AdjustmentBar is loaded to another class called "ExaminationDisplayer" and "I have been able to load the AdjustmentBar into the ExaminationDisplayer"? Also, I can see that your ExaminationDisplayerController extends AdjustmentBarController but it doesn't seem right. Can you throw some light on what are you trying to achieve here? – ItachiUchiha May 11 '17 at 13:28
  • @ItachiUchiha Hi! Yes, the ExaminationDisplayer loads pictures from a database and should display them in an imageView. However, I don't want it to be just a regular ImageView, rather it should be the one I have designed in AdjustmentBar - because that one also has a tool-bar which allows me the zoom / rotate / adjust the contrast for each ImageView. I wasn't able to call for imgView (which is the fixID of the ImageView of AdjustmentBar) unless I added the "extend" command - but maybe that's not right at all. I hope this makes sense! I've also added the Error I get to the post. :-) – Heidi May 11 '17 at 13:36
  • @ItachiUchiha That is, I have a FXML file called ExaminationDisplayer that loads/opens/displays another FXML file called AdjustmentBar. How many AdjustmentBar-ImageViews will be loaded is dependent on how many pictures I want to display at a time. It could be only one, but usually it will be three or four. – Heidi May 11 '17 at 13:41
  • @ItachiUchiha Oh sorry, one explanation more. What I meant by "I have been able to load the AdjustmentBar into the ExaminationDisplayer" is that I can open one AdjustmentBar in ExaminationDisplayer. It shows where the picture should be, and the toolbar is there and I can see that the different functions work (for example if I zoom in). The only thing I can't do is load the image to the imgView. – Heidi May 11 '17 at 13:47
  • 1
    This just isn't how inheritance works. Inheritance is a relationship between classes. When you do `class AdjustmentBarController { private ImageView imgView; }` it means that every `AdjustmentBarController` *instance* has a field called `imgView`. When you write `ExaminationDisplayerController extends AdjustmentBarController`, it means that every `ExaminationDisplayerController` instance is also an instance of `AdjustmentBarController` (which doesn't make sense), and consequently every `ExaminationDisplayerController` instance also has a `imgView` field. (1/2) – James_D May 11 '17 at 14:56
  • 1
    But that doesn't mean that the `imgView` field in one instance is somehow set to the same *value* as the `imgView` field in a different instance. You have two controllers here: one is an instance of `ExaminationDisplayerController`, one is an instance of `AdjustmentBarController`. The way you have it (again, this doesn't make sense), each one has its own `imgView` field. Just because that field is set to a non-null value in one instance doesn't somehow make it non-null in the other instance. (2/2) – James_D May 11 '17 at 14:59
  • @James_D That makes sense, thanks for clearing that up for me! :-) I didn't realize "extends" was a type of inheritance. – Heidi May 11 '17 at 16:04

1 Answers1

2

Whenever you have a requirement and you need to make your controls public, it is a code smell. Never expose your UI nodes.

The best way to do this would be to add a method in the AdjustmentBarController to accept an Image. This method would then set this image in the ImageView defined in the controller.

public class AdjustmentBarController {

    ...

    @FXML
    private ImageView imgView;
    ...
    public void setImage(Image image) {
        imgView.setImage(image);
    }
}

Now, once this is done. Do not extend the ExaminationDisplayerController from AdjustmentBarController.

For every image that you load in the ExaminationDisplayerController, load the FXML file for AdjustmentBar, fetch the controller from the FXMLLoader and set the image in the controller.

// Do not extend from AdjustmentBarController
public class ExaminationDisplayerController {

    ...

    public void SPECTLoad() throws SQLException, ClassNotFoundException {
        DBConnection dbConn = new DBConnection(); 
        ...
        Image image = new Image(new File("SPECT_IMAGE.jpg").toURI().toString(), 200, 200, true, true);
        FXMLLoader loader = new FXMLLoader(getClass().getResource("/fxml/AdjustmentBar.fxml"));
        AnchorPane anchorPaneFromAdjustmentBar = loader.load();
        anchorPane.getChildren().add(anchorPaneFromAdjustmentBar);
        // Get the controller from the FXMLLoader
        AdjustmentBarController controller = (AdjustmentBarController) loader.getController();
        // Set the image
        controller.setImage(image);
        ...
    }
}

For more information, go through:

Community
  • 1
  • 1
ItachiUchiha
  • 36,135
  • 10
  • 122
  • 176
  • Thank you, that helps a lot! I have tried loading an existing image-file from my project with your code and that works perfectly. But unfortunately I still can't display the SPECT_IMAGE.jpg. I think that must be because of something else, so I'm gonna do a little research for what might be wrong. Thank you again! – Heidi May 11 '17 at 16:09
  • 1
    Feel free to ask any additionally questions in the comments below once you are done with your research. – ItachiUchiha May 11 '17 at 16:16
  • 1
    @Heidi image has [error](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html#errorProperty) and [exception](https://docs.oracle.com/javase/8/javafx/api/javafx/scene/image/Image.html#exceptionProperty) properties, try adding listeners to them or querying them to see if there was an image loading error. – jewelsea May 11 '17 at 22:30
  • @ItachiUchiha I just needed to add the "i" to the path of the image - typical beginners mistake :-) Image image = new Image(new File(i + "SPECT_IMAGE.jpg").toURI().toString()); – Heidi May 12 '17 at 09:34