Я создал проект JavaFX в Eclipse, где я храню код Java в папке src, а файлы fxml - в папке ресурсов. Есть несколько компонентов пользовательского интерфейса, которые не имеют соответствующих файлов fxml, например, пользовательская кнопка.
Когда я пытаюсь импортировать такие компоненты в файлы fxml, я получаю следующую ошибку
Вызвано: java.lang.IllegalStateException: Местоположение не установлено.
Я рассмотрел много проблем с ошибкой «java.lang.IllegalStateException: Location is set», но не смог найти ту же проблему, с которой сталкиваюсь.
Для простоты я воспроизвел ошибку с меньшим проектом, где древовидная структура папок src выглядит следующим образом
── src
├── application
│ └── Main.java
├── component
│ └── RoundedButton.java
├── ui
│ └── UIHomePage.java
└── widget
└── ListComboBox.java
и древовидная структура папки ресурсов выглядит следующим образом
── resources
├── ui
│ └── UIHomePage.fxml
└── widget
└── ListComboBox.fxml
Main.java содержит метод start, который может загрузить файл UIHomePage.fxml, контроллером для которого является UIHomePage.java.
RoundedButton.java расширяет класс javafx.scene.control.Button и не использует отдельный файл fxml.
ListComboBox.java расширяет javafx.scene.layout.GridPane и использует ListComboBox.fxml в качестве ресурса fxml.
Проблема, с которой я сталкиваюсь, заключается в том, что когда я пытаюсь загрузить resources / ui / UIHomePage.fxml, он не может определить, где находится ListComboBox, потому что он каким-то образом не может найти src / widget / ComboBox.
У меня есть и папки src, и ресурсы, добавленные как Source в Java Build Path.
Main.java (код метода запуска, загружающий fxml-файл только для UIHomePage.fxml)
Parent root = FXMLLoader.load(getClass().getClassLoader().getResource("ui/UIHomePage.fxml"));
UIHomePage.fxml
<?import javafx.scene.layout.GridPane?>
<?import component.RoundedButton?>
<?import widget.ListComboBox?>
<GridPane fx:controller="ui.UIHomePage" xmlns:fx="http://javafx.com/fxml" alignment="center">
<GridPane GridPane.columnIndex="0" GridPane.rowIndex="0" GridPane.columnSpan="1" GridPane.halignment="CENTER" visible="true" vgap="10" hgap="10">
<ListComboBox fx:id="cityName" GridPane.columnIndex="1" GridPane.rowIndex="0" GridPane.columnSpan="2" GridPane.rowSpan="1"/>
<RoundedButton fx:id="addButton" GridPane.columnIndex="1" GridPane.rowIndex="2" GridPane.columnSpan="1" GridPane.rowSpan="1" text="Add Property" defaultButton="true" onAction="#handleAddProperties"/>
</GridPane>
</GridPane>
UIHomePage.java
import widget.*;
public class UIHomePage {
@FXML private ListComboBox cityName;
@FXML
public void initialize() throws Exception{
cityName.setPrefWidth(GridPane.REMAINING);
}
@FXML
protected void handleAddProperties(ActionEvent event) throws Exception {
//DO SOMETHING
}
}
ListComboBox.fxml
<fx:root type="javafx.scene.layout.GridPane" xmlns:fx="http://javafx.com/fxml">
<ComboBox fx:id="comboBox" GridPane.columnIndex="0" GridPane.rowIndex="0"/>
</fx:root>
ListComboBox.java
public class ListComboBox extends GridPane {
@FXML
private ComboBox<String> comboBox;
public ListComboBox() {
FXMLLoader fxmlLoader = new FXMLLoader(getClass().getResource("widget/ListComboBox.fxml"));
fxmlLoader.setRoot(this);
fxmlLoader.setController(this);
try {
fxmlLoader.load();
} catch (IOException exception) {
throw new RuntimeException(exception);
}
}
}
RoundedButton.java
public class RoundedButton extends Button {
public RoundedButton() {
super();
this.setStyle("-fx-background-radius: 10; -fx-background-color: #eee8aa; -fx-text-fill: #8b4513; -fx-font-size: 3em; ");
}
}
Я надеюсь получить пользовательский интерфейс для загрузки с настраиваемым полем со списком и закругленной кнопкой, но UIHomePage.fxml не может загрузить ListComboBox (настраиваемое поле со списком), и я продолжаю получать следующее сообщение об ошибке
javafx.fxml.LoadException:
/home/gangs/Programming/workspace/Java/TestProject/bin/ui/UIHomePage.fxml:7
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 application.Main.start(Main.java:18)
at com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$161(LauncherImpl.java:863)
at com.sun.javafx.application.PlatformImpl.lambda$runAndWait$174(PlatformImpl.java:326)
at com.sun.javafx.application.PlatformImpl.lambda$null$172(PlatformImpl.java:295)
at java.security.AccessController.doPrivileged(Native Method)
at com.sun.javafx.application.PlatformImpl.lambda$runLater$173(PlatformImpl.java:294)
at com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:95)
at com.sun.glass.ui.gtk.GtkApplication._runLoop(Native Method)
at com.sun.glass.ui.gtk.GtkApplication.lambda$null$48(GtkApplication.java:139)
at java.lang.Thread.run(Thread.java:748)
Caused by: java.lang.IllegalStateException: Location is not set.
at javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2434)
at javafx.fxml.FXMLLoader.load(FXMLLoader.java:2409)
at widget.ListComboBox.<init>(ListComboBox.java:25)
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at java.lang.Class.newInstance(Class.java:442)
at sun.reflect.misc.ReflectUtil.newInstance(ReflectUtil.java:51)
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)
... 17 more
Одно из известных мне решений будет работать, если я поместу все файлы fxml в папку src, но это затруднит управление проектом по мере его роста. Я хочу сохранить эту структуру разделения кода Java и файла fxml в отдельных папках, чтобы в будущем обслуживание кода было проще.
Может кто-нибудь помочь мне понять, что я здесь пропустил?