javafxiconslegacy-code

Why JavaFX shows icon image in IDE project Run, but doesn't show the image in project build?


JavaFX shows icon image in IDE project Run, but doesn't show the image in project build, what is strange about it is that when you click on the space there it should have been the button still performs it's function. To specify the problem I'll show screenshots - the two glitched images are my placeholders: This is run from IDE

This is run from the Jar Build

The only two warnings during build are :

Missing POM for unknown.binary:AbsoluteLayout:jar:SNAPSHOT
Missing POM for unknown.binary:AbsoluteLayout:jar:SNAPSHOT

The project is a legacy code that I inherited so I might not be aware of some obvious solution here.

The curious thing is that if I remove images from the folder in the compiled version (Not in code repo), the images still persist. Which leads me to believe that maybe they are stored in jar build itself ? I kind of expected that the jar wouldn't start without it or the icon images will disappear.

I also tried to change the paths to resources in CSS file like adding "../" to it, but this changed nothing.

gameScreen.fxml:

<?xml version="1.0" encoding="UTF-8"?>

<?scenebuilder-stylesheet vista.css?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.HBox?>

<AnchorPane id="pane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="720.0" prefWidth="1280.0" stylesheets="@../styles/common.css" xmlns="http://javafx.com/javafx/19" xmlns:fx="http://javafx.com/fxml/1" fx:controller="org.balancer.controllers.GameScreenController">
   <children>
      <Button id="goBackButton" layoutX="1100.0" layoutY="34.0" mnemonicParsing="false" onAction="#handleHomeButtonPressed" prefHeight="100.0" prefWidth="100.0" stylesheets="@../styles/common.css" />
      <Label id="screenNameLabel" layoutX="49.0" layoutY="34.0" prefHeight="58.0" prefWidth="457.0" stylesheets="@../styles/common.css" text="Wybierz grę" />
      <HBox id="gamesHBox" alignment="CENTER" layoutX="60.0" layoutY="134.0" prefHeight="288.0" prefWidth="1132.0" spacing="25.0">
         <children>
            <Button id="skiChallengeButton" mnemonicParsing="false" onAction="#skiChallengeButtonHandling" prefHeight="152.0" prefWidth="149.0" stylesheets="@../styles/gameScreen.css" translateX="-80.0" />
            <Button id="jLedButton" mnemonicParsing="false" onAction="#janekLEDButtonHandling" prefHeight="149.0" prefWidth="149.0" stylesheets="@../styles/gameScreen.css" translateX="-80.0" />
            <Button id="archeryButton" mnemonicParsing="false" onAction="#archeryButtonHandling" prefHeight="150.0" prefWidth="150.0" stylesheets="@../styles/gameScreen.css" translateX="-80.0" />
            <Button id="jScoreButton" mnemonicParsing="false" onAction="#janekScoreButtonHandling" prefHeight="150.0" prefWidth="150.0" stylesheets="@../styles/gameScreen.css" translateX="-80.0" />
            <Button id="stuntGPButton" layoutX="693.0" layoutY="79.0" mnemonicParsing="false" onAction="#stuntGPButtonHandling" prefHeight="150.0" prefWidth="150.0" stylesheets="@../styles/gameScreen.css" translateX="-80.0" />
            <Button id="NewGameButton" mnemonicParsing="false" onAction="#NewGameHandling" prefHeight="150.0" prefWidth="150.0" stylesheets="@../styles/gameScreen.css" />
         </children>
      </HBox>
      <HBox id="gamesHBox2" alignment="CENTER" layoutX="106.0" layoutY="415.0" prefHeight="288.0" prefWidth="1068.0" spacing="70.0">
         <children>
            <Button id="NewGameButton" mnemonicParsing="false" onAction="#NewGameHandling" prefHeight="152.0" prefWidth="149.0" stylesheets="@../styles/gameScreen.css" />
         </children>
      </HBox>
   </children>
</AnchorPane>

GameScreen.css

#skiChallengeButton {
    -fx-background-image: url("/images/gameIcons/skichallenge2015Logo.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}
#skiChallengeButton:hover  {
    -fx-background-image: url("/images/gameIcons/skichallenge2015LogoFocused.png");
}

#NewGameButton {
    -fx-background-image: url("/images/gameIcons/New_Game.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}

#NewGameButton:hover {
    -fx-background-image: url("/images/gameIcons/New_Game_Focused.png");
 }

#archeryButton {
    -fx-background-image: url("/images/gameIcons/archeryLogo.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}
#archeryButton:hover  {
    -fx-background-image: url("/images/gameIcons/archeryLogoFocused.png");
}
#jScoreButton {
    -fx-background-image: url("/images/gameIcons/jScoreLogo.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}
#jScoreButton:hover  {
    -fx-background-image: url("/images/gameIcons/jScoreLogoFocused.png");
}
#jLedButton {
    -fx-background-image: url("/images/gameIcons/jLedLogo.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}
#jLedButton:hover  {
    -fx-background-image: url("/images/gameIcons/jLedLogoFocused.png");
}
#stuntGPButton {
    -fx-background-image: url("/images/gameIcons/stuntGPLogo.png");
    -fx-background-position: center center;
    -fx-background-radius: 0;
    -fx-background-color: transparent;
    -fx-background-size: cover;
    -fx-border-width: 0;
}
#stuntGPButton:hover  {
    -fx-background-image: url("/images/gameIcons/stuntGPLogoFocused.png");
}

GameScreenController.java:

import javafx.fxml.Initializable;
import javafx.scene.control.Alert;
import javafx.scene.control.Alert.AlertType;
import javafx.scene.control.Button;
import javafx.scene.control.ButtonType;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.balancer.db.tables.User;
import org.balancer.interpreter.*;
import java.util.Optional;
import org.balancer.PropertiesHelper;

public class GameScreenController implements Initializable, ScreenController {

    @FXML
    Button gameButton;
    Interpreter currentInterpreter;
    ScreenNavigator myNavigator;
    private ResourceBundle strings;
    private static final Logger logger = LogManager.getLogger(GameScreenController.class);

    @Override
    public void setScreenParent(ScreenNavigator screenParent) {
        myNavigator = screenParent;
    }

    public void changeButtonText(String value) {

        gameButton.setText(value);
    }

    @FXML
    private void handleHomeButtonPressed(ActionEvent event) {
        myNavigator.setScreen(ScreenNavigator.homeScreen);
    }

    @FXML
    private void janekLEDButtonHandling(ActionEvent event) {
        showViewerDialogBox();
        currentInterpreter = new JLedInterpreter();
        showInterpreterDialogBox();
    }

    @FXML
    private void janekScoreButtonHandling(ActionEvent event) {
         showViewerDialogBox();
        currentInterpreter = new JScoreInterpreter();
        showInterpreterDialogBox();
    }

    @FXML
    private void archeryButtonHandling(ActionEvent event) {
         showViewerDialogBox();
        currentInterpreter = new ArcheryInterpreter();
        showInterpreterDialogBox();
    }

    @FXML
    private void skiChallengeButtonHandling(ActionEvent event) {
        currentInterpreter = new SkiChallengeInterpreter();
        showInterpreterDialogBox();
    }

    @FXML
    private void stuntGPButtonHandling(ActionEvent event) {
        currentInterpreter = new StuntGPInterpreter();
        showInterpreterDialogBox();
    }
    
    @FXML
    private void NewGameHandling(ActionEvent event) {
        //currentInterpreter = new NewGameKeyboardInterpreter();
        currentInterpreter = new NewGameInterpreter();
        showInterpreterDialogBox();
    }
    


    @Override
    public void initialize(URL location, ResourceBundle resources) {
        Locale locale = User.currentUser.getLocale();
        String bundleName = "stringsBundle." + this.getClass().getSimpleName();
        strings = ResourceBundle.getBundle(bundleName, locale);

The controller file manages the functionality of the buttons and shouldn't be important at all. Do you see anything in the code ? I didn't include it at first because it seemed as a obvious problem, especially that I literally made the "NewGameButton" copying from the previous ones AND that it apparently works in IDE. Which means that code works as intended at least in one place.

Edit 01.03.24

When I say project build I mean just a Jar executable file that I place in the specified folder designed by my predecessors. The specified folder that I will call "app environment" has the following structure: File structure File Structure 2

I've put images folder in multiple places when I was testing if it depends on the location or the existence of said images in the first place. It seems not to. The build command is as follows :

cd D:\projekty\mag\JanekStepInterpreter-master\BalancerInterpreter; "JAVA_HOME=C:\\Program Files\\Java\\jdk1.8.0_211" cmd /c "\"D:\\JDK\\JDK_proper\\NetBeans-17\\netbeans\\java\\maven\\bin\\mvn.cmd\" -Dmaven.ext.class.path=D:\\JDK\\JDK_proper\\NetBeans-17\\netbeans\\java\\maven-nblib\\netbeans-eventspy.jar -Dfile.encoding=UTF-8 --no-transfer-progress clean install" 

It seems it's Maven project. Pom :

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>org.balancer</groupId>
    <artifactId>BalancerInterpreter</artifactId>
    <version>1.0-SNAPSHOT</version>
    <packaging>jar</packaging>
    <dependencies>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
            <version>2.5</version>
        </dependency>
        <dependency>
            <groupId>javax.json</groupId>
            <artifactId>javax.json-api</artifactId>
            <version>1.0</version>
        </dependency>
        <dependency>
            <groupId>org.glassfish</groupId>
            <artifactId>javax.json</artifactId>
            <version>1.1</version>
        </dependency>
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-configuration2</artifactId>
            <version>2.2</version>
        </dependency>
        <dependency>
            <groupId>commons-beanutils</groupId>
            <artifactId>commons-beanutils</artifactId>
            <version>1.9.3</version>
        </dependency>
        <dependency>
            <groupId>com.h2database</groupId>
            <artifactId>h2</artifactId>
            <version>1.4.196</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-core</artifactId>
            <version>4.1.4.Final</version>
        </dependency>
        <dependency>
            <groupId>com.fasterxml.jackson.core</groupId>
            <artifactId>jackson-databind</artifactId>
            <version>2.6.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.hamcrest</groupId>
            <artifactId>hamcrest-core</artifactId>
            <version>1.3</version>
            <scope>test</scope>
        </dependency>
        <dependency>
            <groupId>org.rxtx</groupId>
            <artifactId>rxtx</artifactId>
            <version>2.1.7</version>
        </dependency>
        <dependency>
            <groupId>unknown.binary</groupId>
            <artifactId>AbsoluteLayout</artifactId>
            <version>SNAPSHOT</version>
        </dependency>
       
        <dependency>
            <groupId>org.glassfish.tyrus.bundles</groupId>
            <artifactId>tyrus-standalone-client-jdk</artifactId>
            <version>1.13</version>
        </dependency>
        <dependency>
            <groupId>org.hibernate</groupId>
            <artifactId>hibernate-entitymanager</artifactId>
            <version>4.3.1.Final</version>
        </dependency>
    </dependencies>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>1.8</maven.compiler.source>
        <maven.compiler.target>1.8</maven.compiler.target>
    </properties>
    <build>
        <plugins>
            <plugin>
                <artifactId>maven-assembly-plugin</artifactId>
                <configuration>
                    <archive>
                        <manifest>
                            <mainClass>org.balancer.FxMenu</mainClass>
                        </manifest>
                    </archive>
                    <descriptorRefs>
                        <descriptorRef>jar-with-dependencies</descriptorRef>
                    </descriptorRefs>
                </configuration>
                <executions>
                    <execution>
                        <id>make-assembly</id>
                        <phase>package</phase>
                        <goals>
                            <goal>single</goal>
                        </goals>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
    <repositories>
        <repository>
            <id>unknown-jars-temp-repo</id>
            <name>A temporary repository created by NetBeans for libraries and jars it could not identify. Please replace the dependencies in this repository with correct ones and delete this repository.</name>
            <url>file:${project.basedir}/lib</url>
        </repository>
    </repositories>
    <name>BalancerInterpreter</name>
</project>

In the built project in "target" folder there are : project tree

When you start jar file in target folder it doesn't work. It needs to operate in Balancer 3.0.0.0. folder (inside the "app environment") - that is how this project operates since I got it. I'm sure it needs rxtx-2.1.7 and the app folders to work (Archer, JanekLED etc.) It also needs a glassfish server folder which is a separate project.

When it comes to the position of "images" folder in a jar file, it sits on the top level of the jar : jar file uzipped Which seems to be correct, when looking inside it also consists New_Game.png which is the problematic icon.

I do try to understand and apply What is said in [Eden JavaFx resource Guide] however even if I backctrack the with ../ like this : url(../abc/cde.png) The effect is still the same.

about the icon ID: The upper image was added recently to test if it will appear in the upper HBox since this box was already there in the code when I got it. I thought maybe my newly made HBox is somehow broken. However the effect is still the same no matter if there is only one icon with unique ID or if there are two such icons. Thank you though - I'll proceed to use one or make another ID.

I can't see any module-info.java. neither by looking in my project tree or by using search option in file explorer


Solution

  • It turned out that when I made a brand new icon in paint everything works fine. (Instead of editing existing icon in paint and changing name)

    Sadly I do not know what makes program decide not to show my original image shown in the question but it seems there is a problem with the image file itself.