I am trying to create a simple button, but I am getting this stupid error and it doesn't make any sense.
Here is my Admin Scene FXML:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.ListView?>
<?import javafx.scene.control.Separator?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.text.Font?>
<Pane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="437.0" prefWidth="582.0" stylesheets="#application.css" xmlns="http://javafx.com/javafx/8.0.65" xmlns:fx="http://javafx.com/fxml/1" fx:controller="appController.AdminSceneController">
<children>
<Separator layoutX="-14.0" layoutY="101.0" prefHeight="10.0" prefWidth="601.0" />
<Label layoutX="14.0" layoutY="29.0" text="admin panel">
<font>
<Font name="Book Antiqua" size="28.0" />
</font>
</Label>
<Button layoutX="174.0" layoutY="32.0" mnemonicParsing="false" style="-fx-background-radius: 100px;" text="+" textFill="#369033" />
<Button fx:id="logoutButton" layoutX="14.0" layoutY="65.0" mnemonicParsing="false" onAction="#logout" prefHeight="3.0" prefWidth="81.0" styleClass="logout" stylesheets="#application.css" text="(logout)" textFill="#070707" />
<Button layoutX="387.0" layoutY="392.0" mnemonicParsing="false" prefHeight="31.0" prefWidth="158.0" text="Delete" />
<ListView layoutX="223.0" layoutY="106.0" prefHeight="327.0" prefWidth="128.0" />
</children>
</Pane>
And this is my AdminSceneController.java
package appController;
import appDesign.PhotoAlbum;
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.Node;
import javafx.scene.control.Button;
public class AdminSceneController {
public class MainSceneController {
#FXML
Button logoutButton;
#FXML
public void logout(ActionEvent event) throws Exception {
PhotoAlbum.primaryStage.show();
((Node)(event.getSource())).getScene().getWindow().hide();
}
}
}
I get a warning from Eclipse saying:
The controller 'AdminSceneController' has no event slot 'logout'
And when I run the program, I get the error:
javafx.fxml.LoadException: Error resolving onAction='#logout', either the event handler is not in the Namespace or there is an error in the script.
/C:/Users/Peter/Documents/GitHub/PhotoAlbum40/bin/appDesign/AdminPanelScene.fxml:19
Can anybody help?
Your AdminSceneController does not have a logout method, your class MainSceneController does though.
Remove the line
public class MainSceneController {
and the closing }and it should work.
You have to understand, that an inner class (MainSceneController) is not the same class as the enclosing class (AdminSceneController). By using fx:controller="appController.AdminSceneController" in the fxml a instance of AdminSceneController is created. This class however does not contain a single method or field. This causes the error.
Furthermore note that the FXMLLoader does not allow you to create non-static inner classes. If you want the FXMLLoader to create your controller instance, you have to make MainSceneController static and use fx:controller="appController.AdminSceneController$MainSceneController".
Ways around this would be specifying a controllerFactory or creating the controller instance yourself:
FXMLLoader loader = new FXMLLoader(getClass().getResource(...));
AdminSceneController enclosingInstance = new AdminSceneController(); // or any other way to get your hands on a instance of the enclosing class
// specify controller instance used yourself
loader.setController(enclosingInstance.new MainSceneController());
...
loader.load()
Which requires you to remove the fx:controller attribute from the fxml.
Of course you could also simply move the field / method to a top level class...
Related
This question already has an answer here:
JavaFX, Label null pointer exception
(1 answer)
Closed 1 year ago.
I'm working on a Game project with JavaFX and a MVC Architecture
Here are one of my views
package fr.arnoux23u.javano.mvc.views;
import fr.arnoux23u.javano.mvc.*;
import javafx.fxml.*;
import javafx.scene.control.TextArea;
import java.net.URL;
import java.util.ResourceBundle;
/**
* #author arnoux23u
*/
public class ServerView implements Initializable, Observer {
#FXML
private TextArea clientsList;
#Override
public synchronized void update(Model m) {
System.out.println("[UPDATE] "+Thread.currentThread().getName());
clientsList.setText("test");
}
#Override
public void initialize(URL url, ResourceBundle resourceBundle) {
System.out.println("[INITIALIZE] "+Thread.currentThread().getName());
clientsList.setText("Aucun joueur ici");
}
}
And my FXML File
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<VBox alignment="CENTER" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/17" xmlns:fx="http://javafx.com/fxml/1" fx:controller="fr.arnoux23u.javano.mvc.views.ServerView">
<Label text="JavaNo - Server">
<font>
<Font size="23.0" />
</font>
</Label>
<Label alignment="CENTER" text="Connected Clients">
<font>
<Font size="23.0" />
</font>
</Label>
<TextArea fx:id="clientsList" editable="false" maxWidth="200.0" prefHeight="200.0" prefWidth="200.0" style="-fx-focus-color: -fx-control-inner-background;" text="
">
<VBox.margin>
<Insets top="20.0" />
</VBox.margin>
<font>
<Font size="18.0" />
</font></TextArea>
</VBox>
When I load the app, the text of the TextArea clientsList is correctly set to "Aucun joueur ici" but when I want to update the text (with MVC), I've a NullPointerException on clientsList
First, I thought it was a Thread Error because the Thread who runs the update method was not the "JavaFX Application Thread"
So in my MVC Controller, I use the Platform.runlater() method.
#Override
public void notifyObservers() {
observers.forEach(o -> {
System.out.println("[FOREACH] "+Thread.currentThread().getName());
Platform.runLater(() -> {
System.out.println("[PLATFORM] "+Thread.currentThread().getName());
o.update(this);
});
});
}
The output when I call the update is
[INITIALIZE] JavaFX Application Thread
[FOREACH] Thread-3
[PLATFORM] JavaFX Application Thread
[UPDATE] JavaFX Application Thread
But even with the runLater method, I've a NullPointerException
Here is the complete stack trace
Exception in thread "JavaFX Application Thread" java.lang.NullPointerException: Cannot invoke "javafx.scene.control.TextArea.setText(String)" because "this.clientsList" is null
at fr.arnoux23u.javano/fr.arnoux23u.javano.mvc.views.ServerView.update(ServerView.java:34)
at fr.arnoux23u.javano/fr.arnoux23u.javano.mvc.Game.lambda$notifyObservers$1(Game.java:54)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:457)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:456)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:184)
at java.base/java.lang.Thread.run(Thread.java:833)
I hope someone can help me.
Thank's
See step 3 of this description of FXMLoader operation:
If there is a fx:controller attribute on the root element, the FXMLLoader creates an instance of the specified class.
So, if you create a new instance explicitly in your code, and the loader also creates a new instance, then only the loader instance will have fxml values injected.
I guess, with a high degree of certainty, that is what is happening with your code.
I make a program using FXML. In FXML I create 4 TextFields and Button. My problem is how send parameters from TextFields in FXML to Controller, when I click this button.
I'm make JavaFX application with FXML. I connect this application to database. I searched for the previous week unsuccessfully, but I found nothing special that can help me.
<children>
<BorderPane prefHeight="30.0" prefWidth="700.0">
<bottom>
<AnchorPane>
<children>
<Button text="Add car" fx:id="button" onAction="#AddCar"/>
</children>
</AnchorPane>
</bottom>
</BorderPane>
<TextField promptText="Brand" id="carBrand"/>
<TextField promptText="Model" id="carModel"/>
<TextField promptText="Mileage" id="carMileage"/>
</children>
I expect that I click Button in FXML - Java controller get parameters from FXML and write to the console. Actual I know how to write in console, but my problem is that I don't know how to get brand, model and mileage from FXML.
You need to inject your TextFields into your controller, then query their text properties. To do this, specify an fx:id for each element to be injected and add a field to your controller class with the same type and name. If the field is not public then you need to annotate it with #FXML.
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.VBox?>
<VBox xmlns="http://javafx.com/javafx/12.0.1" xmlns:fx="http://javafx.com/fxml/1"
fx:controller="com.example.Controller" spacing="10" alignment="center">
<TextField fx:id="carBrand" promptText="Brand"/>
<TextField fx:id="carModel" promptText="Model"/>
<TextField fx:id="carMileage" promptText="Mileage"/>
<Button text="Add car" onAction="#addCar"/>
</VBox>
package com.example;
import javafx.fxml.FXML;
import javafx.event.ActionEvent;
import javafx.scene.control.TextField;
public class Controller {
#FXML private TextField carBrand;
#FXML private TextField carModel;
#FXML private TextField carMileage;
#FXML
private void addCar(ActionEvent event) {
event.consume();
String brand = carBrand.getText();
String model = carModel.getText();
String mileage = carMileage.getText();
// do something with values...
}
}
Note: Following Java naming conventions, method names use camelCase. In other words, the button's action method's name should be addCar (like above) rather than AddCar.
I am trying to make basic desktop app using Kotlin and JavaFX(TornadoFX), but I am stuck on setting up controller for FXML file.
I am following guide from edvin on git LINK to git.
The program should increment number in label whenewer is the button clicked.
The problem is..
When I try to use FXML file shown below, I can't use onAction="#increment" to "connect" that file with a controller.
This will compile, but there is no way to call increment function from controller.kt file. Also there is error saying "No controller specified for top level element" ..
Whenever I try to specify the controller by using fx:controller=view.Controller the code will not even compile, showing error:
javafx.fxml.LoadException: Controller value already specified.
Could someone please help me out?
Here is FXML file:
?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.text.Font?>
<BorderPane xmlns="http://javafx.com/javafx/null" xmlns:fx="http://javafx.com/fxml/1">
<padding>
<Insets top="20" right="20" bottom="20" left="20"/>
</padding>
<center>
<VBox alignment="CENTER" spacing="10">
<Label text="0">
<font>
<Font size="20"/>
</font>
</Label>
<Button text="Click to increment" onAction="#increment"/>
</VBox>
</center>
</BorderPane>
Here is MyApp.kt (main file):
package app
import javafx.stage.Stage
import tornadofx.*
import view.MainView
class MyApp: App(MainView::class){
override val primaryView = MainView::class
override fun start(stage: Stage) {
stage.minHeight = 400.0
stage.minWidth = 600.0
super.start(stage)
}
}
Here is MainView.kt (view):
package view
import javafx.scene.layout.BorderPane
import tornadofx.*
class MainView : View() {
override val root: BorderPane by fxml("/views/MainViewFXML.fxml" )
}
Here is Controller.kt (this should be used to control FXML file actions):
package view
class Controller {
fun increment(){
//code
}
}
In TornadoFX, the View IS the controller. Think of View subclasses as the View Controller. React to UI events in the View, and pass business logic off to a ViewModel or a Controller subclass.
Place your increment function in MainView and it will be called :) Remove the fx:controller=view.Controller attribute.
I'm trying to write a simple Java app for modifying and visualizing logic circuits by dragging gates and connections about. I'm using SceneBuilder to put the interface together. Right now, I'm stuck at getting the available basic logic gates to display in their proper bar and respond to being interacted with. More accurately, I'm trying to get one gate to just display some console output, to confirm that the GUI-logic connection is working.
The biggest problem I'm having is that the ImageViews of the gates, possibly along with some other FXML elements, refuse to display in the actual compiled app for some reason, even though they work and react correctly in SceneBuilder and in its "Preview" feature.
I had to do some experimenting with wrapping them in various other FXML elements which I didn't really understand because apparently ImageWiew doesn't have a onDragDetected() method, even though the text input field for it is available in SceneBuilder. The intended work-in-progress app layout can be seen plainly enough directly from SceneBuilder on the first picture. Compare with the second one, which is of the actual running application.
Possibly relevant code:
Main.java
package main;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
#Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource("RootLayout.fxml"));
primaryStage.setTitle("Hello World");
primaryStage.setScene(new Scene(root, 640, 450));
primaryStage.show();
}
public static void main(String[] args) throws Exception {
launch(args);
}
}
TheCircuitController.java
package Gates;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.input.MouseEvent;
import javafx.scene.layout.AnchorPane;
import java.net.URL;
import java.util.ArrayList;
import java.util.ResourceBundle;
/**
* The class for holding all the information about gates, connections, and in and out pins in the current circuit
*/
public class TheCircuitController implements Initializable{
#FXML
private AnchorPane anchorPaneNAND;
//TODO temporarily public, make private later
public ArrayList<CircuitElement> allCircuitElements= new ArrayList<CircuitElement>();
public ArrayList<Pin> theCircuitInputPins = new ArrayList<Pin>();
public ArrayList<Pin> theCircuitOutputPins = new ArrayList<Pin>();
ArrayList<Connection> allCircuitConnections = new ArrayList<Connection>();
public ArrayList<Pin> allCircuitGateInputPins = new ArrayList<Pin>();
public ArrayList<Pin> allCircuitGateOutputPins = new ArrayList<Pin>();
public ArrayList<Gate> allCircuitGates = new ArrayList<Gate>();
private InbuiltGateType currentDragGateType;
#Override
public void initialize(URL fxmlFileLocation, ResourceBundle resources) {
// initialize your logic here: all #FXML variables will have been injected
anchorPaneNAND.setOnDragDetected(this::handleDragDetectedNAND);
}
#FXML
private void handleDragDetectedNAND(MouseEvent mouseEvent) {
System.out.println("drag detected nand!");
}
//other stuff of the class, unrelated to FXML
}
RootLayout.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<VBox maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="450.0" prefWidth="640.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Gates.TheCircuitController">
<children>
<MenuBar prefHeight="27.0" prefWidth="562.0">
<menus>
<Menu mnemonicParsing="false" text="File">
<items>
<MenuItem mnemonicParsing="false" text="Close" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Edit">
<items>
<MenuItem mnemonicParsing="false" text="Delete" />
</items>
</Menu>
<Menu mnemonicParsing="false" text="Help">
<items>
<MenuItem mnemonicParsing="false" text="About" />
</items>
</Menu>
</menus>
</MenuBar>
<SplitPane dividerPositions="0.2413793103448276" prefHeight="402.0" prefWidth="640.0">
<items>
<ScrollPane fitToHeight="true" fitToWidth="true" prefHeight="400.0" prefWidth="122.0">
<content>
<VBox prefHeight="400.0" prefWidth="208.0" spacing="10.0">
<children>
<AnchorPane fx:id="anchorPaneNAND" onDragDetected="#handleDragDetectedNAND">
<children>
<ImageView>
<image>
<Image url="#../../resources/100px-NAND_ANSI.svg.png" />
</image>
</ImageView>
</children>
</AnchorPane>
<ImageView>
<image>
<Image url="#../../resources/100px-NOT_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-AND_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/OR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-NOR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-XOR_ANSI.svg.png" />
</image>
</ImageView>
<ImageView>
<image>
<Image url="#../../resources/100px-XNOR_ANSI.svg.png" />
</image>
</ImageView>
</children>
<padding>
<Insets left="20.0" right="20.0" />
</padding></VBox>
</content></ScrollPane>
<ScrollPane prefHeight="400.0" prefWidth="406.0" />
</items>
</SplitPane>
</children>
</VBox>
I thus need to know:
Why are those gates(or at least one) not displaying as intended? And what's with the ScrollPane, why is it not displaying its sliders as it is in SceneBuilder? What things do I need to set up differently or wiggle with to get those gates to show up and interact correctly?
After a bit of random crapshooting, I found a solution.
First, I looked into View->Show Sample Controller Skeleton. There, I noticed that the handleDragDetectedNAND() method does not have any modifier, whereas mine had private, copied early from some tutorial or the other. I removed the modifier and the application now works. If anyone who passes by cared to explain why this is the case(I have no idea and no time to research, deadline's fast approaching), the value of this answer would rise significantly.
Be sure all images inside of src folder. (tested)
The image which outsite of src folder dont appear.
+ MyProject
+ not_working_dir
+ src
+ com.stackoverflow
+ working_dir
I am currently trying to build a picture viewing program using java and an FXML window. I have had a fiddle about - getting to know FXMLs and accessing them from a program and was able to get buttons to disappear and reappear - but upon adapting said code for this picture viewer, I found that the FXML panel wouldn't open upon running the file. There are no errors/warnings besides warnings about (as yet) unused libraries being declared. Upon start up, there's no error messages, no text boxes and no outputs to the terminal so I can't supply anything from there. The code is as follows:
package practice1;
import javafx.application.Application;
import javafx.stage.Stage;
import java.io.IOException;
import javax.imageio.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import java.io.*;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.layout.*;
import javafx.scene.image.ImageView;
import javafx.scene.image.*;
import java.awt.image.BufferedImage;
public class MainProgram extends Application{
public void start(Stage stage) {
try {
FXMLLoader fxmlLoader = new FXMLLoader();
String viewerFxml = "WindowPanel.fxml";
AnchorPane page = (AnchorPane)fxmlLoader.load(
this.getClass().getResource(viewerFxml).openStream());
Scene scene = new Scene(page);
stage.setScene(scene);
stage.show();
} catch (IOException ex) {
Logger.getLogger(this.getClass().getName()).log(Level.SEVERE, null, ex);
System.exit(1);
}
}
public static void main(String args[]) {
launch(args);
System.exit(0);
}
}
And the FXML is as follows:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.text.*?>
<?import javafx.scene.image.*?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<AnchorPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="400.0" prefWidth="600.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="practice1.MyController">
<children>
<Button fx:id="TurnLeft" layoutX="113.0" layoutY="353.0" mnemonicParsing="false" onAction="#hide1" text="Turn Left" />
<Button fx:id="TurnRight" layoutX="237.0" layoutY="353.0" mnemonicParsing="false" onAction="#hide2" text="Turn Right" />
<ToolBar prefHeight="40.0" prefWidth="600.0">
<items>
<MenuButton mnemonicParsing="false" text="Pick Up">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</MenuButton>
<MenuButton mnemonicParsing="false" text="Drop">
<items>
<MenuItem mnemonicParsing="false" text="Action 1" />
<MenuItem mnemonicParsing="false" text="Action 2" />
</items>
</MenuButton>
</items>
</ToolBar>
<Button fx:id="proceed" layoutX="178.0" layoutY="315.0" mnemonicParsing="false" onAction="#changeImage" text="Proceed" />
<ImageView fx:id="mainImage" fitHeight="259.0" fitWidth="426.0" layoutY="40.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="#Picture1.png" />
</image></ImageView>
<Text layoutX="436.0" layoutY="60.0" strokeType="OUTSIDE" strokeWidth="0.0" text="You have" />
<Text layoutX="436.0" layoutY="86.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Object1" />
<Text layoutX="436.0" layoutY="111.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Object2" />
<Text layoutX="436.0" layoutY="139.0" strokeType="OUTSIDE" strokeWidth="0.0" text="Object 3" />
<ImageView fx:id="SmallImage2" fitHeight="89.0" fitWidth="117.0" layoutX="266.0" layoutY="45.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="SmallImage3" fitHeight="89.0" fitWidth="117.0" layoutX="266.0" layoutY="142.0" pickOnBounds="true" preserveRatio="true" />
<ImageView fx:id="SmallImage1" fitHeight="89.0" fitWidth="117.0" layoutX="152.0" layoutY="45.0" pickOnBounds="true" preserveRatio="true" />
</children>
</AnchorPane>
The file "Picture1.png" is located in the workspace with the position being:
WorkspaceA/Practice1/scr/practice1/Picture1.png
Background
The # notation is used in JavaFX to specify a relative location which is "assumed to be located at a path relative to the current FXML file".
What is Wrong
You load the FXML as a stream using the following code:
AnchorPane page = (AnchorPane)fxmlLoader.load(
this.getClass().getResource(viewerFxml).openStream());
A steam is not a location, so there is no concept of locations relative to the stream.
If I run your application locally, I will get a stack trace where it cannot find the picture file (here is just the last portion of it):
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1081)
... 18 more
How to fix it
Set the location in the loader prior to loading the FXML:
fxmlLoader.setLocation(getClass().getResource(viewerFxml));
AnchorPane page = fxmlLoader.load();
The loader will then be able to resolve the relative reference to your picture file.
Check your directory structure and build output
This may or may not be an issue for you.
You specify your image using the location specifier:
<Image url="#Picture1.png" />
Which tells the FXMLLoader to look for Picture1.png at the same location it got the FXML from; e.g. if you loaded the FXML from the filesystem, the image would be in the same folder on the filesystem as the FXML - similarly if you load the FXML from a jar, the image should be on the same path within the jar as your FXML was retrieved from.
You state that you place your picture at: WorkspaceA/Practice1/scr/practice1/Picture1.png. I'm not sure what that location is, but if it is the same location as your MainProgram.java source, your MyController.java source, WindowPanel.fxml and if your build system is set to copy the image and fxml over to the compile and packaging target directory, then it will work fine - if it's not, you will need to move the image to the appropriate source location.