我不确定我应该把我的
<fx:include fx:id="NTB" source="NTB.fxml" />
放在我的主.fxml文件中的什么地方。我将在底部包含相关文件。
文件结构:
Test.java 显示一个 TableView 以及一个包含一些按钮的工具栏。单击 newTask 按钮时,我试图让它从 NTB.java 调用
display()
方法,这将显示一个新窗口,该窗口接受用户的一些输入并将其存储在该类可见的列表中。一旦用户单击新窗口中的完成按钮,窗口将关闭并更新表格内容。
目前这些文件是如何设置的,程序将编译和运行,当单击 newTask 按钮时,它会产生错误但不会崩溃,这是预期的,因为 NTBController 默认情况下为空,因为
<fx:include />
标签不存在还没有。
我遇到的主要问题是,到目前为止,无论我将
<fx:include />
标记放在 Test.fxml 中的什么位置,该程序都不会启动 产生一个错误,该错误指向测试中包含标记所在的行.fxml,NTB.fxml中BorderPane定义的最后一行,Test.java中的loadFXML&start函数
相关文件:
测试.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<BorderPane maxHeight="-Infinity" maxWidth="-Infinity" minHeight="-Infinity" minWidth="-Infinity" prefHeight="1080.0" prefWidth="1920.0" fx:controller="com.test.Controller" xmlns="http://javafx.com/javafx/13" xmlns:fx="http://javafx.com/fxml/1">
<fx:include fx:id="nTB" source="NTB.fxml" />
<center>
<TableView fx:id="table" prefHeight="352.0" prefWidth="543.0">
<columns>
<TableColumn fx:id="orderCol" prefWidth="75.0" text="Order" />
<TableColumn fx:id="nameCol" prefWidth="75.0" text="Name" />
<TableColumn fx:id="xCol" prefWidth="75.0" text="X" />
<TableColumn fx:id="yCol" prefWidth="75.0" text="Y" />
<TableColumn fx:id="buttonCol" prefWidth="75.0" text="Button" />
<TableColumn fx:id="keyCol" prefWidth="75.0" text="Key Code" />
<TableColumn fx:id="descriptionCol" prefWidth="75.0" text="Description" />
<TableColumn fx:id="delayCol" prefWidth="75.0" text="Delay" />
</columns>
<columnResizePolicy>
<TableView fx:constant="CONSTRAINED_RESIZE_POLICY" />
</columnResizePolicy>
</TableView>
</center>
<top>
<HBox alignment="CENTER" prefHeight="34.0" prefWidth="600.0">
<children>
<Button fx:id="newTask" mnemonicParsing="false" onAction="#newTaskDisplay" text="New" />
<Button fx:id="editTask" mnemonicParsing="false" onAction="#editTasksOnA" text="Edit" />
<Button fx:id="deleteTask" mnemonicParsing="false" onAction="#deleteTasksOnA" text="Delete" />
<Button fx:id="runTasks" mnemonicParsing="false" onAction="#runTasksOnA" text="Run" />
<Label fx:id="numRunsLab" text="Iterations:" />
<TextField fx:id="numRuns" prefHeight="39.0" prefWidth="90.0" promptText="1" />
<Button fx:id="clearTasks" mnemonicParsing="false" onAction="#clearTasksOnA" text="Clear Tasks" />
<Button fx:id="saveTasks" mnemonicParsing="false" onAction="#saveTasksOnA" text="Save" />
<Button fx:id="openTasks" mnemonicParsing="false" onAction="#openTasksOnA" text="Open" />
</children>
</HBox>
</top>
<right>
<VBox alignment="CENTER" prefHeight="945.0" prefWidth="89.0">
<children>
<Button fx:id="moveToTop" mnemonicParsing="false" text="Move Top" />
<Button fx:id="moveUp" mnemonicParsing="false" text="Move Up" />
<Button fx:id="moveDown" mnemonicParsing="false" text="Move Down" />
<Button fx:id="moveToBottom" mnemonicParsing="false" text="Move Bottom" />
</children>
</VBox>
</right>
</BorderPane>
NTB.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.geometry.Insets?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.control.Label?>
<?import javafx.scene.control.TableColumn?>
<?import javafx.scene.control.TableView?>
<?import javafx.scene.control.TextField?>
<?import javafx.scene.control.TextArea?>
<?import javafx.scene.layout.BorderPane?>
<?import javafx.scene.layout.HBox?>
<?import javafx.scene.layout.VBox?>
<?import javafx.scene.control.ChoiceBox?>
<?import javafx.stage.Stage?>
<Stage fx:id="window" fx:controller="com.test.NTB" xmlns="http://javafx.com/javafx/13" xmlns:fx="http://javafx.com/fxml/1" >
<BorderPane >
<center>
<VBox alignment="CENTER">
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="nameLabel" text="Name: " />
</children>
</VBox>
<VBox alignment ="CENTER">
<children>
<TextField fx:id="nameField" promptText="Name..." />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="xLabel" text="X Coord: " />
</children>
</VBox>
<VBox>
<children>
<TextField fx:id="xField" promptText="0.0" />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="yLabel" text="Y Coord: " />
</children>
</VBox>
<VBox>
<children>
<TextField fx:id="yField" promptText="0.0" />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="buttonLabel" text="Button: " />
</children>
</VBox>
<VBox>
<children>
<ChoiceBox fx:id="buttonBox" value="MouseButton.PRIMARY" />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="keyLabel" text="Key: " />
</children>
</VBox>
<VBox>
<children>
<TextField fx:id="keyField" maxWidth="25.0" promptText="A" />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="descriptionLabel" text="Description: " />
</children>
</VBox>
<VBox>
<children>
<TextArea fx:id="descriptionArea" promptText="Enter description..." maxWidth="150" maxHeight="100" />
</children>
</VBox>
</HBox>
<HBox alignment="CENTER">
<padding>
<Insets top="20.0" right="10.0" bottom="0.0" left="5.0" />
</padding>
<VBox alignment="CENTER">
<children>
<Label fx:id="delayLabel" text="Delay: " />
</children>
</VBox>
<VBox>
<children>
<TextField fx:id="delayField" promptText="0" />
</children>
</VBox>
</HBox>
</VBox>
</center>
<bottom>
<HBox alignment="CENTER">
<Button fx:id="doneButton" onAction="#doneButtonOnA" text="Done" />
<Button fx:id="cancelButton" onAction="#cancelButtonOnA" text="Cancel" />
</HBox>
</bottom>
</BorderPane>
</Stage>
Controller.java:
package com.test;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.net.URL;
import java.util.ResourceBundle;
import java.util.Scanner;
import javafx.beans.property.ReadOnlyObjectWrapper;
import javafx.fxml.FXML;
import javafx.fxml.Initializable;
import javafx.scene.control.TableColumn;
import javafx.scene.control.TableView;
import javafx.scene.control.TextField;
import javafx.scene.control.cell.PropertyValueFactory;
import javafx.scene.input.KeyCode;
import javafx.scene.input.MouseButton;
import javafx.stage.FileChooser;
import javafx.stage.Window;
public class Controller extends Test implements Initializable
{
@FXML private TableView<Task> table;
@FXML private TableColumn<Task, Integer> orderCol;
@FXML private TableColumn<Task, String> nameCol;
@FXML private TableColumn<Task, Double> xCol;
@FXML private TableColumn<Task, Double> yCol;
@FXML private TableColumn<Task, MouseButton> buttonCol;
@FXML private TableColumn<Task, String> keyCol;
@FXML private TableColumn<Task, String> descriptionCol;
@FXML private TableColumn<Task, Long> delayCol;
@FXML private TextField numRuns;
@FXML private Window nTB;
@FXML private NTB nTBController;
@Override
public void initialize(URL url, ResourceBundle resources)
{
numRuns.textProperty().addListener((observable, oldValue, newValue) -> {
if(newValue.matches("\\d*")) return;
numRuns.setText(newValue.replaceAll("[^\\d]", ""));
});
orderCol.setCellValueFactory(column-> new ReadOnlyObjectWrapper<Integer>(table.getItems().indexOf(column.getValue()) + 1));
nameCol.setCellValueFactory(new PropertyValueFactory<Task, String>("name"));
xCol.setCellValueFactory(new PropertyValueFactory<Task, Double>("x"));
yCol.setCellValueFactory(new PropertyValueFactory<Task, Double>("y"));
buttonCol.setCellValueFactory(new PropertyValueFactory<Task, MouseButton>("button"));
keyCol.setCellValueFactory(new PropertyValueFactory<Task, String>("keyCode"));
descriptionCol.setCellValueFactory((new PropertyValueFactory<Task, String>("description")));
delayCol.setCellValueFactory(new PropertyValueFactory<Task, Long>("delay"));
table.getItems().setAll(list);
}
@FXML private void newTaskDisplay()
{
nTBController.display();
table.getItems().setAll(list);
}
测试.java:
package com.test;
import javafx.application.Application;
import javafx.collections.FXCollections;
import javafx.collections.ObservableList;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
import java.io.IOException;
public class Test extends Application {
private static Scene scene;
protected static Stage stage;
protected static ObservableList<Task> list = FXCollections.observableArrayList();
@Override
public void start(Stage primStage) throws IOException {
stage = primStage;
scene = new Scene(loadFXML("Test"), 640, 480);
scene.getStylesheets().add(getClass().getResource("Test.css").toExternalForm());
stage.setScene(scene);
stage.show();
}
static void setRoot(String fxml) throws IOException {
scene.setRoot(loadFXML(fxml));
}
private static Parent loadFXML(String fxml) throws IOException {
FXMLLoader fxmlLoader = new FXMLLoader(Test.class.getResource(fxml + ".fxml"));
return fxmlLoader.load();
}
public static void main(String[] args) {
launch();
}
}
运行错误:
Exception in Application start method
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:119)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplicationWithArgs(LauncherImpl.java:464)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication(LauncherImpl.java:363)
at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
at java.base/java.lang.reflect.Method.invoke(Method.java:577)
at java.base/sun.launcher.LauncherHelper$FXHelper.main(LauncherHelper.java:1081)
Caused by: java.lang.RuntimeException: Exception in Application start method
at javafx.graphics/com.sun.javafx.application.LauncherImpl.launchApplication1(LauncherImpl.java:900)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication$2(LauncherImpl.java:195)
at java.base/java.lang.Thread.run(Thread.java:833)
Caused by: javafx.fxml.LoadException: Element does not define a default property.
/C:/Users/dylan/Desktop/testing/test/target/classes/com/test/NTB.fxml:133
/C:/Users/dylan/Desktop/testing/test/target/classes/com/test/Test.fxml:15
at javafx.fxml/javafx.fxml.FXMLLoader.constructLoadException(FXMLLoader.java:2621)
at javafx.fxml/javafx.fxml.FXMLLoader$Element.set(FXMLLoader.java:187)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processEndElement(FXMLLoader.java:798)
at javafx.fxml/javafx.fxml.FXMLLoader.processEndElement(FXMLLoader.java:2838)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2557)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader$IncludeElement.constructValue(FXMLLoader.java:1154)
at javafx.fxml/javafx.fxml.FXMLLoader$ValueElement.processStartElement(FXMLLoader.java:754)
at javafx.fxml/javafx.fxml.FXMLLoader.processStartElement(FXMLLoader.java:2722)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2552)
at javafx.fxml/javafx.fxml.FXMLLoader.loadImpl(FXMLLoader.java:2466)
at javafx.fxml/javafx.fxml.FXMLLoader.load(FXMLLoader.java:2435)
at com.test/com.test.Test.loadFXML(Test.java:36)
at com.test/com.test.Test.start(Test.java:23)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:399)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
... 1 more
Exception running application com.test.Test
要包含在 Test.fxml 中的标签:
<fx:include fx:id="NTB" source="NTB.fxml" />
如果有任何其他信息对此有帮助,请询问,我很乐意提供。
我也不会死心塌地地让这成为这个程序的最终结构,所以如果这做起来不必要地困难,并且有更简单的方法来完成同样的事情,请告诉我。我是将 fxml 与 JavaFX 结合使用的新手,所以我还不确定最好的方法。
这里是错误:
Caused by: javafx.fxml.LoadException: Element does not define a default property.
/C:/Users/dylan/Desktop/testing/test/target/classes/com/test/NTB.fxml:133
/C:/Users/dylan/Desktop/testing/test/target/classes/com/test/Test.fxml:15
此错误(具体而言)与
fx:include
元素的位置无关。问题是 NTB.fxml
文件中的元素没有定义 default 属性。它说错误发生在 FXML 文件的133
行。该行是结束 </BorderPane>
标签。这是有道理的,因为父元素定义了一个Stage
,它确实没有定义默认属性。
当你遇到这样的事情时:
<VBox>
<Label/>
</VBox>
这将
Label
放入 VBox
的子列表中。之所以可行,是因为 Pane
被注释为 @DefaultProperty("children")
。 那个注释是@Inherited
,所以VBox
有相同的注释。因此,直接位于 <VBox>
元素内的元素将应用于 children
属性。如果该注释不存在,那么您需要执行以下操作:
<VBox>
<children>
<Label/>
</children>
</VBox>
Stage
类没有@DefaultProperty
注释。它的任何超类也没有。这意味着您不能直接将元素放置在 <Stage>
元素内。您必须告诉 FXML 您要设置哪个属性。
这会导致另一个问题。您不能将
BorderPane
放在 Stage
中。您需要先将其包装为 Scene
的根。像这样的东西:
<Stage>
<scene>
<Scene width="-1" height="-1">
<!-- The Scene class is annotated with DefaultProperty("root") -->
<BorderPane>
<!-- your stuff -->
</BorderPane>
</Scene>
</scene>
</Stage>
不幸的是,这导致了另一个问题。您正在尝试将
NBT.fxml
嵌入到另一个 FXML 文件中。您不能将 Stage
放在另一个 Stage
中(更不用说另一个 Node
了)。您要么需要重新考虑您的设计,要么需要将 NBT.fxml
的根元素定义为某种 Node
而不是 Stage
。
如果您决定在这里继续使用
fx:include
(意味着您将根元素更改为Node
的一种),请记住BorderPane
从@DefaultProperty
继承了它的Pane
注释。这意味着它的默认属性是children
。不应将节点直接添加到边框窗格的子节点;那个孩子不会得到妥善管理。确保将 fx:include
元素移动到 <top>
、<left>
、<bottom>
、<right>
或 <center>
元素内。