Fxml 需要获得与其所在的 fxml 相同的控制器
Fxml needs to get same controller as fxml that it is in
我有一个用 fxml 编写的边框面板,它的左面板和中间面板的布局可以互换。
borderpane fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="mainBorderPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Program.gui.MainSceneController">
<left>
<ScrollPane fitToWidth="true" BorderPane.alignment="CENTER">
<content>
<VBox id="sideMenu" spacing="10.0" styleClass="side-menu">
<children>
<Button fx:id="buttonCash" contentDisplay="TOP" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonCashPress" styleClass="side-menu-button" text="Cash">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/pos.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonUsers" contentDisplay="TOP" layoutX="10.0" layoutY="10.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonUsersPress" styleClass="side-menu-button" text="Users">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/users.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonInventory" contentDisplay="TOP" layoutX="10.0" layoutY="35.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonInventoryPress" styleClass="side-menu-button" text="Inventory">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/inventory.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonCustomers" contentDisplay="TOP" layoutX="10.0" layoutY="60.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonCustomersPress" styleClass="side-menu-button" text="customers">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/customers.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonLogout" contentDisplay="TOP" layoutX="31.0" layoutY="232.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonLogoutPress" styleClass="side-menu-button" text="Log out">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/log_out.png" />
</image>
</ImageView>
</graphic>
</Button>
</children>
</VBox>
</content>
<BorderPane.margin>
<Insets />
</BorderPane.margin>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</ScrollPane>
</left>
<bottom>
<HBox BorderPane.alignment="CENTER">
<children>
<Label fx:id="currentUserLabel" styleClass="current-user-label" text="Current user: name here">
<font>
<Font size="15.0" />
</font>
</Label>
<AnchorPane HBox.hgrow="ALWAYS" />
<Label fx:id="currentTimeLabel" layoutX="10.0" layoutY="10.0" styleClass="current-time-label" text="TIME">
<font>
<Font size="15.0" />
</font>
</Label>
<AnchorPane layoutX="170.0" layoutY="10.0" HBox.hgrow="ALWAYS" />
<Label fx:id="currentDateLabel" layoutX="170.0" layoutY="10.0" styleClass="current-date-label" text="DATE">
<font>
<Font size="15.0" />
</font>
</Label>
</children>
<padding>
<Insets left="10.0" right="10.0" />
</padding>
</HBox>
</bottom>
<stylesheets>
<URL value="@ScreenStylesheet.css" />
</stylesheets>
</BorderPane>
fxml 文件中的其中一个按钮将 运行 控制器中的一些代码,用于使用从另一个 fxml 文件加载的 VBox 更改边框的右侧。
现在的问题是如何告诉右窗格的 fxml 使用与主边框窗格相同的控制器?换句话说我想继承控制器。
如果我在它的 fxml 中使用 fx:controller="Program.gui.MainSceneController"
定义控制器,它只会创建一个新实例,如果我不定义它,它只会出错,因为它里面的按钮没有控制器参考。
编辑:
有人在这里询问更改屏幕右侧的代码是:
(注意:这个是在controller里面找到的)
//mainBorderPane is gotten from the main fxml file.
FXMLLoader loader = new FXMLLoader(getClass().getResource("cashRightArea.fxml"));
mainBorderPane.setRight(loader.load());
如果您想将特定控制器分配给视图,您可以这样做:
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane minHeight="400.0" minWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Label fx:id="myLabel" layoutX="28.0" layoutY="53.0" text="Label" />
<Accordion layoutX="42.0" layoutY="158.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
<AnchorPane fx:id="childContainer" layoutX="56.0" layoutY="177.0" maxHeight="200.0" minHeight="200.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
<Button fx:id="loadChild" layoutX="135.0" layoutY="43.0" mnemonicParsing="false" text="Load child panel" />
</children>
</AnchorPane>
MainController.java:
public class MainController implements Initializable{
@FXML
protected Label myLabel;
@FXML
private Button loadChild;
@FXML
private AnchorPane childContainer;
@FXML
protected Button updateButton;
StringProperty myStringProp=new SimpleStringProperty();
private void loadChildpanel() {
System.out.println(this.hashCode());
FXMLLoader loader = new FXMLLoader(getClass().getResource("Child.fxml"));
Node childNode;
try {
loader.setController(this);
childNode = (Node) loader.load();
childContainer.getChildren().add(childNode);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void updateLabel() {
myStringProp.setValue("updated text");
System.out.println(this.hashCode());
}
@Override
public void initialize(URL location, ResourceBundle resources) {
myStringProp.set("Initial text");
loadChild.setOnAction(e->loadChildpanel());
myLabel.textProperty().bind(myStringProp);
if(updateButton!=null)updateButton.setOnAction(e->updateLabel());
}
}
Child.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="100.0" prefWidth="180.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Button fx:id="updateButton" layoutX="10.0" layoutY="18.0" mnemonicParsing="false" prefHeight="65.0" prefWidth="161.0" text="Update" />
</children>
</AnchorPane>
确保您没有在 Child.fxml 文件中指定控制器。
这个解决方案有效,子视图中的按钮可以更新主视图上的标签。
但是,这是一个令人讨厌的解决方案,对不同的视图使用相同的控制器不是好的做法。有视图控制器对更干净。当您需要显示另一个视图时,您可以从父控制器执行以下操作:
FXMLLoader loader = new
FXMLLoader(getClass().getResource(InterfaceToNetworkController.UI_PATH));
Node rootNode = (Parent) loader.load();
InterfaceToNetworkController childController = loader.getController();
mainBorderPane.setRight(rootNode);
希望对您有所帮助
我有一个用 fxml 编写的边框面板,它的左面板和中间面板的布局可以互换。
borderpane fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.image.*?>
<?import java.net.*?>
<?import javafx.geometry.*?>
<?import javafx.scene.text.*?>
<?import java.lang.*?>
<?import java.util.*?>
<?import javafx.scene.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<BorderPane fx:id="mainBorderPane" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="Program.gui.MainSceneController">
<left>
<ScrollPane fitToWidth="true" BorderPane.alignment="CENTER">
<content>
<VBox id="sideMenu" spacing="10.0" styleClass="side-menu">
<children>
<Button fx:id="buttonCash" contentDisplay="TOP" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonCashPress" styleClass="side-menu-button" text="Cash">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/pos.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonUsers" contentDisplay="TOP" layoutX="10.0" layoutY="10.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonUsersPress" styleClass="side-menu-button" text="Users">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/users.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonInventory" contentDisplay="TOP" layoutX="10.0" layoutY="35.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonInventoryPress" styleClass="side-menu-button" text="Inventory">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/inventory.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonCustomers" contentDisplay="TOP" layoutX="10.0" layoutY="60.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonCustomersPress" styleClass="side-menu-button" text="customers">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/customers.png" />
</image>
</ImageView>
</graphic></Button>
<Button fx:id="buttonLogout" contentDisplay="TOP" layoutX="31.0" layoutY="232.0" maxWidth="1.7976931348623157E308" mnemonicParsing="false" onAction="#buttonLogoutPress" styleClass="side-menu-button" text="Log out">
<cursor>
<Cursor fx:constant="HAND" />
</cursor>
<graphic>
<ImageView fitHeight="50.0" fitWidth="50.0" pickOnBounds="true" preserveRatio="true">
<image>
<Image url="@../../Libraries/Icons/log_out.png" />
</image>
</ImageView>
</graphic>
</Button>
</children>
</VBox>
</content>
<BorderPane.margin>
<Insets />
</BorderPane.margin>
<padding>
<Insets bottom="5.0" left="5.0" right="5.0" top="5.0" />
</padding>
</ScrollPane>
</left>
<bottom>
<HBox BorderPane.alignment="CENTER">
<children>
<Label fx:id="currentUserLabel" styleClass="current-user-label" text="Current user: name here">
<font>
<Font size="15.0" />
</font>
</Label>
<AnchorPane HBox.hgrow="ALWAYS" />
<Label fx:id="currentTimeLabel" layoutX="10.0" layoutY="10.0" styleClass="current-time-label" text="TIME">
<font>
<Font size="15.0" />
</font>
</Label>
<AnchorPane layoutX="170.0" layoutY="10.0" HBox.hgrow="ALWAYS" />
<Label fx:id="currentDateLabel" layoutX="170.0" layoutY="10.0" styleClass="current-date-label" text="DATE">
<font>
<Font size="15.0" />
</font>
</Label>
</children>
<padding>
<Insets left="10.0" right="10.0" />
</padding>
</HBox>
</bottom>
<stylesheets>
<URL value="@ScreenStylesheet.css" />
</stylesheets>
</BorderPane>
fxml 文件中的其中一个按钮将 运行 控制器中的一些代码,用于使用从另一个 fxml 文件加载的 VBox 更改边框的右侧。
现在的问题是如何告诉右窗格的 fxml 使用与主边框窗格相同的控制器?换句话说我想继承控制器。
如果我在它的 fxml 中使用 fx:controller="Program.gui.MainSceneController"
定义控制器,它只会创建一个新实例,如果我不定义它,它只会出错,因为它里面的按钮没有控制器参考。
编辑: 有人在这里询问更改屏幕右侧的代码是: (注意:这个是在controller里面找到的)
//mainBorderPane is gotten from the main fxml file.
FXMLLoader loader = new FXMLLoader(getClass().getResource("cashRightArea.fxml"));
mainBorderPane.setRight(loader.load());
如果您想将特定控制器分配给视图,您可以这样做:
Main.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.*?>
<?import java.lang.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane minHeight="400.0" minWidth="400.0" xmlns="http://javafx.com/javafx/8" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.MainController">
<children>
<Label fx:id="myLabel" layoutX="28.0" layoutY="53.0" text="Label" />
<Accordion layoutX="42.0" layoutY="158.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
<AnchorPane fx:id="childContainer" layoutX="56.0" layoutY="177.0" maxHeight="200.0" minHeight="200.0" prefHeight="200.0" prefWidth="200.0" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" />
<Button fx:id="loadChild" layoutX="135.0" layoutY="43.0" mnemonicParsing="false" text="Load child panel" />
</children>
</AnchorPane>
MainController.java:
public class MainController implements Initializable{
@FXML
protected Label myLabel;
@FXML
private Button loadChild;
@FXML
private AnchorPane childContainer;
@FXML
protected Button updateButton;
StringProperty myStringProp=new SimpleStringProperty();
private void loadChildpanel() {
System.out.println(this.hashCode());
FXMLLoader loader = new FXMLLoader(getClass().getResource("Child.fxml"));
Node childNode;
try {
loader.setController(this);
childNode = (Node) loader.load();
childContainer.getChildren().add(childNode);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private void updateLabel() {
myStringProp.setValue("updated text");
System.out.println(this.hashCode());
}
@Override
public void initialize(URL location, ResourceBundle resources) {
myStringProp.set("Initial text");
loadChild.setOnAction(e->loadChildpanel());
myLabel.textProperty().bind(myStringProp);
if(updateButton!=null)updateButton.setOnAction(e->updateLabel());
}
}
Child.fxml:
<?xml version="1.0" encoding="UTF-8"?>
<?import java.lang.*?>
<?import javafx.scene.control.*?>
<?import javafx.scene.layout.*?>
<?import javafx.scene.layout.AnchorPane?>
<AnchorPane prefHeight="100.0" prefWidth="180.0" xmlns:fx="http://javafx.com/fxml/1" xmlns="http://javafx.com/javafx/8">
<children>
<Button fx:id="updateButton" layoutX="10.0" layoutY="18.0" mnemonicParsing="false" prefHeight="65.0" prefWidth="161.0" text="Update" />
</children>
</AnchorPane>
确保您没有在 Child.fxml 文件中指定控制器。 这个解决方案有效,子视图中的按钮可以更新主视图上的标签。
但是,这是一个令人讨厌的解决方案,对不同的视图使用相同的控制器不是好的做法。有视图控制器对更干净。当您需要显示另一个视图时,您可以从父控制器执行以下操作:
FXMLLoader loader = new
FXMLLoader(getClass().getResource(InterfaceToNetworkController.UI_PATH));
Node rootNode = (Parent) loader.load();
InterfaceToNetworkController childController = loader.getController();
mainBorderPane.setRight(rootNode);
希望对您有所帮助