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();
}
}