简体   繁体   中英

Java FX Changing ImageView image or image URL?

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.

Your problem:

card = new ImageView("images/cards/Ad.png");

This is invalid code. You created the card in the FXML . When you say = new ImageView(...); , you are effectively no longer referencing the Card/ImageView create in the FXML .

If you need to initialize the Card/ImageView in the initialize method do:

@Override
public void initialize(URL url, ResourceBundle rb)
{
    Image image = new Image(getClass().getResourceAsStream("/images/cards/Ad.png"));
    card.setFitHeight(100); //726
    card.setFitWidth(200); //500
    card.setImage(image);
}

There are two methodsTo load images (I prefare)
The way mentioned by Sedrick is used when you wanna embed the images folder inside the jar (package) file, But if you wanna make the jar light weight and leave the images folder outside of the jar I'd rather use this way

card.setImage(new Image("file:images/cards/As.png"));

where file keyword make the file browser start looking from the project folder in our case JavaFXApplication1

The most consistent way I could do it - using Netbeans as my IDE - was

new Image(JavaFXApplication1.class.getClass().getResource("/img/card.jpg").toString());

And my project directory source structure has the img directory on the same level as the package. From the file system, from the .java file it is ../img/card.jpg , but using GetResource points it to the equivalent of your .../JavaFXApplication1/src/ directory

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM