Во-первых, чтобы ответить на непосредственную проблему, конечная причина ошибки определяется трассировкой стека:
Caused by: java.lang.IllegalArgumentException: Invalid URL or resource not found
at javafx.scene.image.Image.validateUrl(Image.java:1110)
... 55 more
Это означает, что URL ("x.png"
), который вы даете конструктору Image
, недействителен. Либо вы использовали неправильный путь, либо ресурс находится не там, где вы думаете. В комментариях вы упоминаете, что ваш файл изображения находится в том же каталоге, что и ваши .java
файлы. Если вы используете Maven или Gradle, для ресурсов по умолчанию используется src/main/resources
(и src/main/java
для *.java
файлов). Если это чистый JavaBX-проект NetBeans (который может использовать Ant?), Я не знаю, куда должны идти ресурсы. Посмотрите, есть ли каталог, предназначенный для ресурсов, и, если он есть, переместите туда все файлы ресурсов.
В вашем коде есть пара ошибок:
private void handleNewGameAction(ActionEvent event) throws IOException {
FXMLLoader fxmlloader = new FXMLLoader(getClass().getResource("FXMLDocument.fxml"));
GridPane pane = (GridPane)fxmlloader.getNamespace().get("topGrid");
Image image = new Image("x.png");
pane.add(new ImageView(image), 0, 0);
}
Первый выпуск посвящен fxmlloader.getNamespace().get("topGrid")
. Вы звоните по этому номеру только что созданного FXMLLoader
и еще не звонили load()
. Результат этого вызова всегда будет null
, потому что FXMLLoader
на самом деле еще ничего не создавал.
Вторая, и, на мой взгляд, более крупная проблема связана с тем, что вы создаете новую GridPane
каждый раз, когда вызывается этот метод. Этот новый GridPane
никогда не добавляется ни к одному Scene
, и поэтому графический интерфейс никогда не будет обновляться. И чтобы быть ясным, GridPane
, который вы извлекаете в методе , не тот, который уже отображается . И когда метод завершается, GridPane
выпадает из области видимости и подвергается сборке мусора.
Поскольку вы создаете игровую доску, вам необходимо загружать доску только один раз (или, может быть, один раз за игру). После этого вы используете загруженную доску для добавления изображений в. Вы должны использовать класс контроллера, связанный с файлом FXML.
import javafx.event.ActionEvent;
import javafx.fxml.FXML;
import javafx.scene.image.ImageView;
import javafx.scene.layout.GridPane;
public class Controller {
@FXML
private GridPane topGrid;
@FXML
private void handleAction(ActionEvent event) {
topGrid.add(new ImageView(/*image*/), 0, 0);
event.consume();
}
}
Чтобы связать контроллер с файлом FXML, вы должны использовать или атрибут fx:controller
в файле или , который вы будете использовать FXMLLoader.setController(Object)
перед вызовом метода load()
экземпляра , Чтобы получить контроллер, вы можете использовать FXMLLoader.getController()
после вызова load.
Чтобы узнать больше о FXML в JavaFX, см. Введение в FXML .