Heidi
Heidi

Reputation: 71

Javafx setImage for ImageView from another FXML-controller

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 :-)

Upvotes: 1

Views: 3131

Answers (1)

ItachiUchiha
ItachiUchiha

Reputation: 36722

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:

Upvotes: 2

Related Questions