I am very new to Java FX. I am trying to create a card game application with scene builder for fun but have been having issues changing the image of ImageView components.
The src folder contains two packages, one for the all the images and the other containing all the code.
In the controller class, I've tried to change the image by using many combinations of the following, where the card is an ImageView
component, which matches the fx:id
of the ImageView
in SceneBuilder
:
card.setImage(new Image("../images/cards/As.png");
card.setImage(new Image("@../images/cards/As.png");
card.setImage(new Image(getClass().getResource("As.png").toExternalForm()));
card.setImage(new Image("File:..images/cards/As.png"));
In every scenario, I end up getting either an "Invalid URL or Resource not found" or "Null Pointer" exception.
If I go to the .fxml and edit the URL to "@../images/cards/As.png", for example, then it works but when using the setImage method I can't do it.
I got those ideas from other threads on here where they worked for other people it seems. Are my images in the wrong place? Is it not possible to change the image URL of something in the .fxml file? If anyone can help me out with this i would appreciate it very much.
Project Structure:
I started a new project, called JavaFXApplication1, to test image changing functionality. I am trying to do this with the click of a button. There are two source packages, as you can see from the project structure above. There is the 'images' package that just contains all of the .pngs i want to use in my application, and then the other package is called 'javafxapplication1', containing 3 files. Below is the code for each:
FXMLDocument.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<AnchorPane id="AnchorPane" prefHeight="200" prefWidth="320" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="javafxapplication1.FXMLDocumentController">
<children>
<Button fx:id="button" layoutX="126" layoutY="90" onAction="#handleButtonAction" text="Click Me!" />
<Label fx:id="label" layoutX="126" layoutY="120" minHeight="16" minWidth="69" />
<ImageView id="rat" fx:id="card" cache="true" fitHeight="105.0" fitWidth="118.0" layoutX="39.0" layoutY="24.0" pickOnBounds="true" preserveRatio="true" AnchorPane.leftAnchor="39.0" AnchorPane.rightAnchor="208.68595123291016">
<image>
<Image url="@../images/cards/back.png" />
</image></ImageView>
</children>
</AnchorPane>
FXMLDocumentController.java
package javafxapplication1;
import java.io.File;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.Button;
import javafx.scene.control.Label;
import javafx.scene.image.Image;
import javafx.scene.image.ImageView;
/**
*
* @author wesley
*/
public class FXMLDocumentController implements Initializable {
@FXML
private Label label;
@FXML
private ImageView card;
@FXML
private Button button;
@FXML
private void handleButtonAction(ActionEvent event) {
System.out.println("You clicked me!");
label.setText("Hello World!");
System.out.println(getClass().getResourceAsStream("/images/cards/As.png"));
Image image = new Image(getClass().getResourceAsStream("/images/cards/As.png"));
card.setFitHeight(726); //726
card.setFitWidth(500); //500
card.setImage(image);
System.out.println("You changed the pic ");
}
@Override
public void initialize(URL url, ResourceBundle rb)
{
//File file = new File("/images/cards/Ad.png");
//Image image = new Image(file.toURI().toString());
card = new ImageView("images/cards/Ad.png");
//card.setFitHeight(726); //726
// card.setFitWidth(500); //500
}
}
JavaFXApplication1.java
package javafxapplication1;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
/**
*
* @author
*/
public class JavaFXApplication1 extends Application {
@Override
public void start(Stage stage) throws Exception {
Parent root = FXMLLoader.load(getClass().getResource("FXMLDocument.fxml"));
Scene scene = new Scene(root);
stage.setScene(scene);
stage.show();
}
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
launch(args);
}
}
When I run the application, It loads fine, with the image there that was defined in scene builder (Note: I use a document relative path, not sure if this is ideal or could be an issue). Upon clicking the button, the setImage call executes, but I see no change in the image. I know it executes because this is my output:
You clicked me! sun.net.www.protocol.jar.JarURLConnection$JarURLInputStream@1db87651 You changed the pic
Also, I'm not sure if I should be setting the fitHeight and width from the initialize method or not.