0

I have been working on a JavaFX project with Maven. I am using JDK 14 with IntelliJ IDE to compile my project into a JAR artifact.

I have linked the CSS files into FXML through Scene Builder. The CSS files contain necessary background image information.

The program runs perfectly inside the IDE. But it is showing the following error when I run as a JAR.

Error loading image: jar:file:/C:/Users/Sajed/Desktop/GitHub/IFTAS/out/artifacts/IFTAS_jar/IFTAS.jar!/tgtList/main.jpg

My project structure is like the following:

src  
  -main  
    -java  
      -tgtList
        -Java File
    -resources
      -tgtList
        -FXML file
        -main.jpg
        -backgorund.css

Can someone point me out the possible areas I should be concerned with?

pom.xml

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xmlns="http://maven.apache.org/POM/4.0.0"
         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.sajed</groupId>
    <artifactId>IFTA</artifactId>
    <version>1.0.0.0</version>
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        <maven.compiler.source>14</maven.compiler.source>
        <maven.compiler.target>14</maven.compiler.target>
    </properties>
    <dependencies>
        <!-- https://mvnrepository.com/artifact/com.jfoenix/jfoenix -->
        <dependency>
            <groupId>com.jfoenix</groupId>
            <artifactId>jfoenix</artifactId>
            <version>9.0.10</version>
        </dependency>

        <!-- https://mvnrepository.com/artifact/org.xerial/sqlite-jdbc -->
        <dependency>
            <groupId>org.xerial</groupId>
            <artifactId>sqlite-jdbc</artifactId>
            <version>3.32.3.2</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/com.itextpdf/itext7-core -->
        <dependency>
            <groupId>com.itextpdf</groupId>
            <artifactId>itext7-core</artifactId>
            <version>7.1.13</version>
            <type>pom</type>
        </dependency>
        <dependency>
            <groupId>org.projectlombok</groupId>
            <artifactId>lombok</artifactId>
            <version>1.18.16</version>
            <scope>provided</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx</artifactId>
            <version>16-ea+4</version>
            <type>pom</type>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-fxml -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-fxml</artifactId>
            <version>16-ea+4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-controls -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-controls</artifactId>
            <version>16-ea+4</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.openjfx/javafx-graphics -->
        <dependency>
            <groupId>org.openjfx</groupId>
            <artifactId>javafx-graphics</artifactId>
            <version>16-ea+4</version>
        </dependency>
    </dependencies>

</project>

background.css

.mainbg{
   -fx-background-image: url('main.jpg');
   -fx-background-size: 100% 100%;    
}

Tgt.fxml:

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

<?import com.jfoenix.controls.JFXButton?>
<?import com.jfoenix.controls.JFXComboBox?>
<?import com.jfoenix.controls.JFXTextField?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>

<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="600.0" minWidth="800.0" styleClass="mainbg" stylesheets="@background.css" xmlns="http://javafx.com/javafx/11.0.1" xmlns:fx="http://javafx.com/fxml/1" fx:controller="tgtList.TgtController">
    <center>
        <TableView fx:id="tableView" prefHeight="200.0" prefWidth="200.0" BorderPane.alignment="CENTER">
            <columns>
                <TableColumn fx:id="id" prefWidth="50.0" text="Id" visible="false" />
                <TableColumn fx:id="ser" prefWidth="50.0" text="Ser" />
                <TableColumn fx:id="tgtName" prefWidth="190.0" text="Name" />
                <TableColumn fx:id="tgtSize" prefWidth="150.0" text="Size" />
                <TableColumn fx:id="tgtPosture" prefWidth="180.0" text="Posture" />
                <TableColumn fx:id="terr" prefWidth="115.0" text="Terr" />
            </columns>
        </TableView>
    </center>
    <top>
        <GridPane BorderPane.alignment="CENTER">
            <columnConstraints>
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
                <ColumnConstraints hgrow="SOMETIMES" minWidth="10.0" prefWidth="100.0" />
            </columnConstraints>
            <rowConstraints>
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
                <RowConstraints minHeight="10.0" prefHeight="30.0" vgrow="SOMETIMES" />
            </rowConstraints>
            <children>
                <JFXComboBox fx:id="fieldTgtSize" promptText="Select" GridPane.columnIndex="3" GridPane.rowIndex="2" />
                <Label text="Tgt Size" GridPane.columnIndex="2" GridPane.rowIndex="2">
                    <GridPane.margin>
                        <Insets left="20.0" />
                    </GridPane.margin>
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </Label>
                <Label alignment="CENTER" contentDisplay="CENTER" text="TGT ASSESSMENT" underline="true" GridPane.columnIndex="1" GridPane.columnSpan="2" GridPane.halignment="CENTER">
                    <font>
                        <Font name="System Bold" size="18.0" />
                    </font>
                </Label>
                <JFXButton fx:id="add" buttonType="RAISED" onAction="#add" style="-fx-background-color: green;" text="Add" textFill="WHITE" GridPane.columnIndex="2" GridPane.rowIndex="6">
                    <GridPane.margin>
                        <Insets left="20.0" />
                    </GridPane.margin>
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </JFXButton>
                <Label text="Posture" GridPane.rowIndex="4">
                    <GridPane.margin>
                        <Insets left="20.0" />
                    </GridPane.margin>
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </Label>
                <JFXComboBox fx:id="fieldPosture" focusColor="#4ca128" promptText="Select" GridPane.columnIndex="1" GridPane.rowIndex="4" />
                <Label text="Tgt Name" GridPane.rowIndex="2">
                    <GridPane.margin>
                        <Insets left="20.0" />
                    </GridPane.margin>
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </Label>
                <JFXTextField fx:id="fieldTgtName" focusColor="#4ca128" promptText="Write Tgt Name" GridPane.columnIndex="1" GridPane.rowIndex="2">
                    <GridPane.margin>
                        <Insets right="30.0" />
                    </GridPane.margin>
                </JFXTextField>
                <Label text="Terr" GridPane.columnIndex="2" GridPane.rowIndex="4">
                    <GridPane.margin>
                        <Insets left="20.0" />
                    </GridPane.margin>
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </Label>
                <JFXComboBox fx:id="fieldTerr" focusColor="#4ca128" promptText="Select" GridPane.columnIndex="3" GridPane.rowIndex="4" />
                <JFXButton fx:id="delete" buttonType="RAISED" onAction="#deleteFromDb" style="-fx-background-color: red;" text="Delete" textFill="WHITE" GridPane.columnIndex="3" GridPane.rowIndex="6">
                    <font>
                        <Font name="System Bold" size="14.0" />
                    </font>
                </JFXButton>
            </children>
        </GridPane>
    </top>
</BorderPane>

TgtController.java

package tgtList;

import com.jfoenix.controls.JFXButton;
import com.jfoenix.controls.JFXComboBox;
import com.jfoenix.controls.JFXTextField;
import constants.IConstants;
import database.TgtDB;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.*;
import javafx.scene.control.cell.ComboBoxTableCell;
import javafx.scene.control.cell.TextFieldTableCell;
import javafx.scene.input.KeyCode;
import model.TgtModel;

import java.net.URL;
import java.util.Arrays;
import java.util.ResourceBundle;
import java.util.Set;
import java.util.stream.Collectors;

public class TgtController implements Initializable {

    private static final TgtDB tgtDb = new TgtDB();
    ObservableList<TgtModel> obs = FXCollections.observableArrayList();
    @FXML
    TableView<TgtModel> tableView;
    @FXML
    TableColumn<TgtModel, String> id = new TableColumn<>();
    @FXML
    TableColumn<TgtModel, String> ser = new TableColumn<>();
    @FXML
    TableColumn<TgtModel, String> tgtName = new TableColumn<>();
    @FXML
    TableColumn<TgtModel, String> tgtSize = new TableColumn<>();
    @FXML
    TableColumn<TgtModel, String> tgtPosture = new TableColumn<>();
    @FXML
    TableColumn<TgtModel, String> terr = new TableColumn<>();

    @FXML
    JFXTextField fieldTgtName = new JFXTextField();
    @FXML
    JFXComboBox<Label> fieldTgtSize = new JFXComboBox<>();
    @FXML
    JFXComboBox<Label> fieldPosture = new JFXComboBox<>();
    @FXML
    JFXComboBox<Label> fieldTerr = new JFXComboBox<>();

    @FXML
    JFXButton add;
    @FXML
    JFXButton delete;

    private static void getErrorPopUp() {

        Alert alert = new Alert(Alert.AlertType.ERROR);
        alert.setHeaderText("Duplicate Tgt Name");
        alert.showAndWait();
    }

    @Override
    public void initialize(URL location, ResourceBundle resources) {

        fieldTgtSize.getItems().addAll(Arrays.stream(IConstants.tgtSizeList).map(Label::new).collect(Collectors.toList()));
        fieldPosture.getItems().addAll(Arrays.stream(IConstants.postureList).map(Label::new).collect(Collectors.toList()));
        fieldTerr.getItems().addAll(Arrays.stream(IConstants.terrList).map(Label::new).collect(Collectors.toList()));

        loadDB();
        tableView.setItems(obs);

        //System.out.println( obs );

        ser.setCellValueFactory(cellData -> cellData.getValue().ser());
        id.setCellValueFactory(cellData -> cellData.getValue().id());
        tgtName.setCellValueFactory(cellData -> cellData.getValue().tgtName());
        tgtName.setCellFactory(TextFieldTableCell.forTableColumn());
        tgtName.setOnEditCommit(
                (TableColumn.CellEditEvent<TgtModel, String> t) -> {

                    if (!t.getNewValue().trim().equals("")) {
                        t.getTableView().getItems().get(
                                t.getTablePosition().getRow()).setTgtName(t.getNewValue());
                        updateDB();
                    }
                    loadDB();
                });

        tgtSize.setCellValueFactory(cellData -> cellData.getValue().tgtSize());
        tgtSize.setCellFactory(ComboBoxTableCell.forTableColumn(IConstants.tgtSizeList));
        tgtSize.setOnEditCommit(
                (TableColumn.CellEditEvent<TgtModel, String> t) -> {
                    if (!t.getNewValue().trim().equals("")) {
                        t.getTableView().getItems().get(
                                t.getTablePosition().getRow()).setTgtSize(t.getNewValue());
                        updateDB();
                    }
                    loadDB();
                });

        tgtPosture.setCellValueFactory(cellData -> cellData.getValue().tgtPosture());
        tgtPosture.setCellFactory(ComboBoxTableCell.forTableColumn(IConstants.postureList));
        tgtPosture.setOnEditCommit(
                (TableColumn.CellEditEvent<TgtModel, String> t) -> {
                    if (!t.getNewValue().trim().equals("")) {
                        t.getTableView().getItems().get(
                                t.getTablePosition().getRow()).setTgtPosture(t.getNewValue());
                        updateDB();
                    }
                    loadDB();
                });

        terr.setCellValueFactory(cellData -> cellData.getValue().terr());
        terr.setCellFactory(ComboBoxTableCell.forTableColumn(IConstants.terrList));
        terr.setOnEditCommit(
                (TableColumn.CellEditEvent<TgtModel, String> t) -> {
                    if (!t.getNewValue().trim().equals("")) {
                        t.getTableView().getItems().get(
                                t.getTablePosition().getRow()).setTerr(t.getNewValue());
                        updateDB();
                    }
                    loadDB();
                });

        setTableEditable();
    }

    private void setTableEditable() {
        tableView.setEditable(true);
        tableView.getSelectionModel().cellSelectionEnabledProperty().set(true);
        tableView.setOnKeyPressed(event -> {
            if (event.getCode().isLetterKey() || event.getCode().isDigitKey()) {
                editFocusedCell();
            } else if (event.getCode() == KeyCode.RIGHT
                    || event.getCode() == KeyCode.TAB) {
                tableView.getSelectionModel().selectNext();
                event.consume();
            } else if (event.getCode() == KeyCode.LEFT) {
                tableView.getSelectionModel().selectPrevious();
                event.consume();
            }
        });
    }

    @SuppressWarnings("unchecked")
    private void editFocusedCell() {
        final TablePosition<TgtModel, ?> focusedCell = tableView
                .focusModelProperty().get().focusedCellProperty().get();
        tableView.edit(focusedCell.getRow(), focusedCell.getTableColumn());
    }

    @FXML
    private void add() {
        Set<String> nameSet = obs.stream().map(s -> s.tgtName().getValue()).collect(Collectors.toSet());
        System.out.println(nameSet);
        if (nameSet.contains(fieldTgtName.getText().trim())) {
            getErrorPopUp();
            return;
        }
        if (fieldTgtName.getText().trim().equals("")) return;
        if (fieldTgtSize.getValue() == null || fieldTgtSize.getValue().getText().trim().equals("")) return;
        if (fieldPosture.getValue() == null || fieldPosture.getValue().getText().trim().equals("")) return;
        if (fieldTerr.getValue() == null || fieldTerr.getValue().getText().trim().equals("")) return;

        TgtModel temp = new TgtModel(fieldTgtName.getText().trim(), fieldTgtSize.getValue().getText().trim(),
                fieldPosture.getValue().getText().trim(),
                fieldTerr.getValue().getText().trim());

        tgtDb.addTgt(temp);
        loadDB();

        fieldTgtName.clear();
        fieldTgtSize.getSelectionModel().clearSelection();
        fieldPosture.getSelectionModel().clearSelection();
        fieldTerr.getSelectionModel().clearSelection();
    }

    private void loadDB() {
        obs.clear();
        obs.addAll(tgtDb.tgtList());
    }

    private void updateDB() {
        tgtDb.UpdateDb(obs);
    }

    @FXML
    private void deleteFromDb() {

        TgtModel tgt = tableView.getSelectionModel().getSelectedItem();
        if (tgt == null) return;
        tableView.getItems().removeAll(tableView.getSelectionModel().getSelectedItems());

        tgtDb.deleteFromDb(tgt);
        updateDB();
    }
}
Naman
  • 27,789
  • 26
  • 218
  • 353
  • Your project structure doesn't seem to indicate a `tgtList` folder anywhere. Show the actual code you are using to load the images. – James_D Nov 19 '20 at 18:01
  • @James_D I have updated the structure for your reference. Thank you. – Sajed Jalil Nov 19 '20 at 18:04
  • Post the code as well. – James_D Nov 19 '20 at 18:07
  • And, since the path it's trying to load from looks correct, you probably want to check the content of the jar file to see if `main.jpg` is included and is in the expected location. Use `jar -tf IFTAS.jar` from the command line (in the appropriate directory). See https://stackoverflow.com/questions/61531317/how-do-i-determine-the-correct-path-for-fxml-files-css-files-images-and-other – James_D Nov 19 '20 at 18:12
  • Thank you @James_D I have used WinRAR to view the inside contents of the jar. The image is where it should be. Still could not fix it. – Sajed Jalil Nov 19 '20 at 18:18
  • That all looks correct. It's definitely `main.jpg`, not `Main.jpg`, or any other variation? – James_D Nov 19 '20 at 18:20
  • @James_D Yes, it is main.jpg. Do you think it could be an issue with the IntelliJ IDE? Should I try using NetBeans or Eclipse? – Sajed Jalil Nov 19 '20 at 18:23
  • IDE makes no difference. – James_D Nov 19 '20 at 18:49
  • strip it down to a [mcve] - for your own sake: you don't need all the unrelated stuff to troubleshoot a resource you can't load for any reason .. – kleopatra Nov 20 '20 at 10:15
  • Although it is late, I have solved the problem. Could not identify the core problem but assuming it is an IDE issue of IntelliJ. Opened a new project and gradually added package by package and it works fine now. – Sajed Jalil Dec 07 '20 at 10:47

0 Answers0