0

I'm trying to set the imageView img_1 with the 1st image of my database. For some reason it doesn't work and I can't figure out why. The method loadImage is called in a different class.

public class MainMenuController implements Initializable 
{
    /**
     * Initializes the controller class.
    */
    @Override
       public void initialize(URL url, ResourceBundle rb) {
       // TODO
    }

    //DBConnect dbimg = new DBConnect();
    @FXML
    private void openSecondWindow(ActionEvent event) {
    try {
        GUIController ctrl = new GUIController();
        ctrl.loadImg();
        //ctrl.firstScreen();
    } catch (Exception e) {
        System.out.println(e.getMessage());
    }
}

I also tried setting the image in a separate method, but I need it called at the same time as the whole stage scene etc is created, even after calling it like that from a second method it doesn't work.

Here is the class holding the setImage

@FXML
private ImageView img_1;

@FXML
private AnchorPane stck1;

ResultSet rs = null;
Statement stmnt = null;
Connection con = null;

String host = "jdbc:derby://localhost:1527/InteractiveGameDatabase;allowMultiQueries=true";
String unm = "Kylar";
String pswrd = "aswzxc";

BufferedImage imgt = null;
InputStream fis = null;
int xcoord;
int ycoord;
int newcoord;

String SQL = "SELECT*FROM location";


public ImageView loadImg() throws IOException {

    try {

        Stage stage = new Stage();
           AnchorPane stck1 = ((AnchorPane) FXMLLoader.load(InteractiveFictionGame2.class.getResource("GUI.fxml")));

        stck1.getChildren().addAll();
        Scene scene = new Scene(stck1);
        stage.setTitle("Interactive Fiction Game");
        stage.setScene(scene);
        stage.sizeToScene();
        stage.show();

        String SQL = "SELECT*FROM location";
        con = DriverManager.getConnection(host, unm, pswrd);
        stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
        rs = stmnt.executeQuery(SQL);
        rs.next();
        fis = rs.getBinaryStream(4);
        imgt = javax.imageio.ImageIO.read(fis);
        Image newImg = SwingFXUtils.toFXImage(imgt, null);

Setting the image gives me a value null when called, the default value for imageview is null but I am actually loading an image even checked with newImg.isError() - which came back as "image loaded = true" . The next method call on button click is to set the imageView again and that works.

        img_1.setImage(newImg)
        rs.close();
        stmnt.close();
        con.close();
    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
    return img_1;
}

This is the second method which works

public ImageView goNorth() throws IOException { try {

        String SQLNorth = "select vista from location where ycoordinate = ? and xcoordinate = ?";
        System.out.println("coords are" + xcoord + ycoord);
        newcoord = ycoord + 1;
        System.out.println("New coord x and y are" + xcoord + newcoord);

        con = DriverManager.getConnection(host, unm, pswrd);
        stmnt2 = con.prepareStatement(SQLNorth);
        stmnt2.setInt(1, newcoord);
        stmnt2.setInt(2, xcoord);
        rs = stmnt2.executeQuery();
        rs.next();
        fis2 = rs.getBinaryStream(1);
        imgt2 = javax.imageio.ImageIO.read(fis2);
        Image newImg = SwingFXUtils.toFXImage(imgt2, null);
        img_1.setImage(newImg);


    } catch (SQLException e) {
        System.out.println(e.getMessage());
    }
    return img_1;
}

I don't understand exactly how am I to fetch the controller the whole class is the controller ?! What is the correct way to do it, I was just looking at the getClass() method and I can't understand am I calling the getClass on a class or on the whole package and in the path specifying which class I'm setting as the controller ?

@FXML
 private void openSecondWindow(ActionEvent event) {
        try {
            FXMLLoader loader;
            loader = new FXMLLoader(GUIController.class.getClass().getResource("GUI.fxml").toExternalForm());
            Parent parent =loader.load();
            GUIController ctrl = loader.getController();
            ctrl.loadImg();
            //ctrl.firstScreen();
        } catch (Exception e) {
            System.out.println(e.getMessage());
        }
    }
1
  • with your last example you need to set parent to scene of your new window. If thats what openSecondWindow method do Commented Apr 14, 2015 at 8:56

2 Answers 2

1

The problem is GUIController ctrl = new GUIController();

The problem with the first approach is that fields annotated with @FXML only gets instantiated when you load the fxml. Initializing controller with new doesn't do it.

Instead of initializing a controller, fetch it from the FXMLLoader

FMLLoader loader = new FXMLLoader(getClass().getResource("SOME_PATH").toExternalForm());
Parent parent = loader.load();
GUIController ctrl = loader.getController();

EDIT - Answers to further questions

I can't understand am I calling the getClass on a class

You don't have to. You either use

getClass().getResource("SOME_PATH")

or you use

GUIController.class.getResource("SOME_PATH")

both will give you the same result.

in the path specifying which class I'm setting as the controller

Since you haven't added any fxml in your question and I will make a guess and say that GUI.fxml just looks as:

<AnchorPane fx:id="vbox" prefHeight="117.0" prefWidth="285.0" xmlns="http://javafx.com/javafx/8" 
        xmlns:fx="http://javafx.com/fxml/1" fx:controller="package.GUIController">
    <children>
        ...
    </children>
</AnchorPane>

Your controller is the class specified in fx:controller="package.GUIController" and loader.getController() will return an instance of the GUIController class.

Sign up to request clarification or add additional context in comments.

5 Comments

what is this parent for then ?
Parent is the base class for all nodes that have children in the scene graph. You can replace it with the root layout of your fxml.
@KylarStern I have added answers to your further questions
Still don't quite understand how it works but it does, thanks dude. I'm new here btw :)
@KylarStern Did you read my explanation? If you have further questions ask them in the comments.
0

I think this would be more proper way if your goal is to open new window with new scene. First, make the new stage, load fxml and set the scene in MainMenuController. This will keep things separate.

@FXML
 private void openSecondWindow(ActionEvent event) {
        try {
            Stage stage = new Stage();
            FXMLLoader loader = new FXMLLoader(getClass().getResource("GUI.fxml"));
            Parent parent = loader.load();
            stage.setTitle("Interactive Fiction Game");      
            stage.setScene(new Scene(parent));
            GUIController ctrl = loader.getController();
            ctrl.loadImg();
            //ctrl.firstScreen();

            stage.show();
            } catch (Exception e) {
                System.out.println(e.getMessage());
            }
        }

In this code I see you are overriting stck1 when there is no need to, stck1 is already initialized variable.

public ImageView loadImg() throws IOException {

    try {


        String SQL = "SELECT*FROM location";
        con = DriverManager.getConnection(host, unm, pswrd);
        stmnt = con.createStatement(ResultSet.TYPE_SCROLL_SENSITIVE, ResultSet.CONCUR_READ_ONLY);
        rs = stmnt.executeQuery(SQL);
        rs.next();
        fis = rs.getBinaryStream(4);
        imgt = javax.imageio.ImageIO.read(fis);
        Image newImg = SwingFXUtils.toFXImage(imgt, null);

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.