Я пытаюсь сгенерировать исполняемый jar-файл из проекта JavaFX, над которым я работаю: работает нормально при выполнении в Eclipse IDE.
Но при выполнении из сгенерированного файла JAR возникает ошибка времени выполнения, когда FXML
пытается загрузить пользовательский компонент (класс, который extends
компонент JFX BorderPane
).
Что не так?
Вот файл FXML
, где используется пользовательский класс CardPane
, который расширяет BorderPane
.
<?xml version="1.0" encoding="UTF-8"?>
<?import com.tsi.ui.CardPane?>
<?import java.lang.*?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.ColumnConstraints?>
<?import javafx.scene.layout.GridPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.Pane?>
<?import javafx.scene.layout.RowConstraints?>
<?import javafx.scene.text.Font?>
<?import com.tsi.ui.CardPane?>
<BorderPane fx:id="mainPane" maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="500.0" prefWidth="400.0" style="-fx-background-color: #454449;" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1">
<center>
<GridPane fx:id="gridPane" opacity="0.99" prefHeight="386.0" prefWidth="380.0" 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>
<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>
<children>
<!--
The below command (referenced in the stack trace as line 40,
which here is not precise, since I've deleted some useless
stuff for the post propose) is where the error occurs
-->
<CardPane fx:id="pane00" prefHeight="200.0" prefWidth="200.0" />
<CardPane fx:id="pane01" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" />
<CardPane fx:id="pane02" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" />
<CardPane fx:id="pane10" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="1" />
<CardPane fx:id="pane11" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<CardPane fx:id="pane12" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="1" />
<CardPane fx:id="pane20" prefHeight="200.0" prefWidth="200.0" GridPane.rowIndex="2" />
<CardPane fx:id="pane21" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="1" GridPane.rowIndex="2" />
<CardPane fx:id="pane22" prefHeight="200.0" prefWidth="200.0" GridPane.columnIndex="2" GridPane.rowIndex="2" />
</children>
</GridPane>
</center>
<!-- I will show only the interesting point -->
...
</BorderPane>
CardPane используется просто как класс, расширяющий BorderPane с позициями макета, уже заполненными некоторыми другими узлами. В этом коде у нас есть некоторые из них, заполняющие содержимое ячеек GridPane.
Вот несколько строк, чтобы показать, как это определено:
public class CardPane extends BorderPane {
private Card card;
private Label cardName;
private Label cardValue;
private ImageView valueIcon;
private HBox hBox;
private Node armaSprite;
public CardPane() {
hBox = new HBox();
cardName = new Label();
cardValue = new Label();
valueIcon = new ImageView(new Image(Sprite.CAMINHO + File.separator + "CoracaoIcon.png", 27, 22, false, false));
}
Честно говоря, я не знаю, является ли этот подход (расширение класса BorderPane
, создание моего собственного компонента таким образом) хорошей практикой. Если нет, я буду рад, если кто-то может дать мне знать, чего следует избегать.
Но, прежде всего, главное, что все хорошо работает внутри Eclipse, но не при экспорте проекта. Зачем?
Вот исключение, напечатанное на консоли Windows. Опять же, это происходит только тогда, когда банка выполняется с java.exe -jar '.\Dungeon Cards.jar'
Никогда в IDE.
javafx.fxml.LoadException:
file:/C:/Users/ramon/Desktop/Dungeon%20Cards.jar!/com/tsi/ui/fxml/game.fxml:40
at javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2601)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2579)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2441)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3214)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3175)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3148)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3124)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:3104)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:3097)
at com.tsi.app.Jogo.<init>(Jogo.java:40)
at com.tsi.app.DungeonCards.iniciarJogo(DungeonCards.java:138)
at com.tsi.ui.Instrucoes.esconder(Instrucoes.java:72)
at com.tsi.ui.Instrucoes$2.handle(Instrucoes.java:52)
at com.tsi.ui.Instrucoes$2.handle(Instrucoes.java:1)
at com.sun.javafx.event.CompositeEventHandler$NormalEventHandlerRecord.handleBubblingEvent(CompositeEventHandler.java:218)
at com.sun.javafx.event.CompositeEventHandler.dispatchBubblingEvent(CompositeEventHandler.java:80)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:238)
at com.sun.javafx.event.EventHandlerManager.dispatchBubblingEvent(EventHandlerManager.java:191)
at com.sun.javafx.event.CompositeEventDispatcher.dispatchBubblingEvent(CompositeEventDispatcher.java:59)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:58)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.BasicEventDispatcher.dispatchEvent(BasicEventDispatcher.java:56)
at com.sun.javafx.event.EventDispatchChainImpl.dispatchEvent(EventDispatchChainImpl.java:114)
at com.sun.javafx.event.EventUtil.fireEventImpl(EventUtil.java:74)
at com.sun.javafx.event.EventUtil.fireEvent(EventUtil.java:54)
at javafx.event.Event.fireEvent(Event.java:198)
at javafx.scene.Scene$KeyHandler.process(Scene.java:3964)
at javafx.scene.Scene$KeyHandler.access$1800(Scene.java:3910)
at javafx.scene.Scene.impl_processKeyEvent(Scene.java:2040)
at javafx.scene.Scene$ScenePeerListener.keyEvent(Scene.java:2501)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:217)
at com.sun.javafx.tk.quantum.GlassViewEventHandler$KeyEventNotification.run(GlassViewEventHandler.java:149)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.lambda$handleKeyEvent$352(GlassViewEventHandler.java:248)
at com.sun.javafx.tk.quantum.QuantumToolkit.runWithoutRenderLock(QuantumToolkit.java:389)
at com.sun.javafx.tk.quantum.GlassViewEventHandler.handleKeyEvent(GlassViewEventHandler.java:247)
at com.sun.glass.ui.View.handleKeyEvent(View.java:546)
at com.sun.glass.ui.View.notifyKey(View.java:966)
at com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at com.sun.glass.ui.win.WinApplication.lambda$null$147(WinApplication.java:177)
at java.lang.Thread.run(Unknown Source)
Caused by: java.lang.IllegalArgumentException: Invalid URL: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1118)
at javafx.scene.image.Image.<init>(Image.java:659)
at com.tsi.ui.CardPane.<init>(CardPane.java:42)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(Unknown Source)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(Unknown Source)
at java.lang.reflect.Constructor.newInstance(Unknown Source)
at java.lang.Class.newInstance(Unknown Source)
at sun.reflect.misc.ReflectUtil.newInstance(Unknown Source)
at javafx.fxml.FXMLLoader$InstanceDeclarationElement.constructValue(FXMLLoader.java:1009)
at javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:746)
at javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2707)
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2527)
... 39 more
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1110)
... 51 more