嵌入式 fxml 上的 JavaFX-8 setRoot 导致光标闪烁和内存/cpu 资源问题
JavaFX-8 setRoot on embedded fxml causes cursor flickering and memory / cpu resource issues
我想在 JavaFX 中构建向导式应用程序。因此,我有一个带有导航按钮的 wizard.fxml
和每个 step/task 的空 AnchorPane,它们分别位于单独的 fxml 文件中,以便在运行时将它们嵌入到(主)向导中。
现在,当我想在 WizardController 中调用第一步时:
FXMLLoader loader = SpringFXMLLoader.getLoader(this.getClass().getClassLoader().getResource("logon.fxml")); //creates a loader with the current application context
loader.setController(this);
loader.setRoot(this.taskPane /*The AnchorPane*/);
loader.load();
它按预期加载但我遇到了这个问题:现在每当我将鼠标悬停在按钮或 TextField 之类的东西上时,光标开始在 "hand"-光标和 "default"- 之间闪烁光标。 wizard.fxml
中的按钮闪烁但仍在工作,但我无法单击 and/or 在嵌入式 logon.fxml
的文本字段中键入内容。我想这可能与重叠对象有关,所以我为每个节点禁用了 PickOnBounds
但问题仍然存在。另外运行程序非常消耗CPU和RAM资源,我什至无法流畅地拖动程序windows。
使用此代码(logon.fxml 中没有 fx:root):
FXMLLoader loader = SpringFXMLLoader.getLoader(this.getClass().getClassLoader().getResource("logon.fxml")); //creates a loader with the current application context
loader.setController(this);
Node task = loader.load();
taskPane.getChildren().clear();
taskPane.getChildren().add(task);
AnchorPane.setTopAnchor(task, 0d);
AnchorPane.setRightAnchor(task, 0d);
AnchorPane.setBottomAnchor(task, 0d);
AnchorPane.setLeftAnchor(task, 0d);
给了我完全相同的输出和问题。当我注释掉单行 loader.load();
时,问题没有出现,但显然我需要加载。
wizard.fxml(无导入)
<BorderPane stylesheets="@application.css" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="path.to.my.controller.WizardController">
<bottom>
<ButtonBar id="buttonBar" BorderPane.alignment="CENTER">
<buttons>
<Button id="btnPrevious" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="< Zurück" />
<Button id="btnNext" alignment="CENTER" contentDisplay="CENTER" defaultButton="true" mnemonicParsing="false" pickOnBounds="false" text="Weiter >" />
<Button id="btnFinish" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="Fertigstellen" />
<Button id="btnCancel" alignment="CENTER" cancelButton="true" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="Abbrechen" />
</buttons>
</ButtonBar>
</bottom>
<center>
<AnchorPane fx:id="taskPane" pickOnBounds="false" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
logon.fxml(含fx:root)
<fx:root type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TitledPane alignment="TOP_LEFT" animated="false" collapsible="false" contentDisplay="CENTER" pickOnBounds="false" styleClass="taskPane" stylesheets="@application.css" text="Logon" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font name="System Bold" size="18.0" />
</font>
<content>
<GridPane maxHeight="150.0" maxWidth="250.0" pickOnBounds="false" styleClass="inputGrid">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="94.0" minWidth="10.0" prefWidth="58.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="140.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>
<Label pickOnBounds="false" text="Mandant" />
<Label pickOnBounds="false" text="Benutzer" GridPane.rowIndex="1" />
<Label pickOnBounds="false" text="Kennwort" GridPane.rowIndex="2" />
<TextField id="fldMandant" fx:id="fldMandant" pickOnBounds="false" GridPane.columnIndex="1" />
<TextField fx:id="fldBenutzer" pickOnBounds="false" prefWidth="110.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="fldKennwort" pickOnBounds="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
</children>
</GridPane>
</content>
</TitledPane>
</children>
</fx:root>
好的,所以这个问题是偶然的 recursion/loop。我执行的从 FXML 加载节点的代码在 initialize(URL, ResourceBundle)
方法中。现在,将新加载的 fxml 的控制器设置为 相同的 控制器对象,从创建它的地方 (loader.setController(this);
) 导致 initialize(URL, ResourceBundle)
-method 运行 并因此再次加载相同的 fxml 。这永远不会停止。
我的解决方案是删除 loader.setController(this);
调用并(更重要的是)将 fxml 本身中的控制器设置为某个 other 控制器。为了保持控制器之间的连接,我创建了一个名为 SubController
的接口。所有代表 step/task 而不是向导本身的控制器都实现了它。该接口指定了我要转发给 SubController 的四个 onButtonClick 方法。事件的实际处理现在发生在 SubController 中。
@FXML
void onCancel(ActionEvent event)
{
this.currentSub.onCancel(event);
}
@FXML
void onFinish(ActionEvent event)
{
this.currentSub.onFinish(event);
}
@FXML
void onNext(ActionEvent event)
{
this.currentSub.onNext(event);
}
@FXML
void onPrevious(ActionEvent event)
{
this.currentSub.onPrevious(event);
}
我想在 JavaFX 中构建向导式应用程序。因此,我有一个带有导航按钮的 wizard.fxml
和每个 step/task 的空 AnchorPane,它们分别位于单独的 fxml 文件中,以便在运行时将它们嵌入到(主)向导中。
现在,当我想在 WizardController 中调用第一步时:
FXMLLoader loader = SpringFXMLLoader.getLoader(this.getClass().getClassLoader().getResource("logon.fxml")); //creates a loader with the current application context
loader.setController(this);
loader.setRoot(this.taskPane /*The AnchorPane*/);
loader.load();
它按预期加载但我遇到了这个问题:现在每当我将鼠标悬停在按钮或 TextField 之类的东西上时,光标开始在 "hand"-光标和 "default"- 之间闪烁光标。 wizard.fxml
中的按钮闪烁但仍在工作,但我无法单击 and/or 在嵌入式 logon.fxml
的文本字段中键入内容。我想这可能与重叠对象有关,所以我为每个节点禁用了 PickOnBounds
但问题仍然存在。另外运行程序非常消耗CPU和RAM资源,我什至无法流畅地拖动程序windows。
使用此代码(logon.fxml 中没有 fx:root):
FXMLLoader loader = SpringFXMLLoader.getLoader(this.getClass().getClassLoader().getResource("logon.fxml")); //creates a loader with the current application context
loader.setController(this);
Node task = loader.load();
taskPane.getChildren().clear();
taskPane.getChildren().add(task);
AnchorPane.setTopAnchor(task, 0d);
AnchorPane.setRightAnchor(task, 0d);
AnchorPane.setBottomAnchor(task, 0d);
AnchorPane.setLeftAnchor(task, 0d);
给了我完全相同的输出和问题。当我注释掉单行 loader.load();
时,问题没有出现,但显然我需要加载。
wizard.fxml(无导入)
<BorderPane stylesheets="@application.css" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1" fx:controller="path.to.my.controller.WizardController">
<bottom>
<ButtonBar id="buttonBar" BorderPane.alignment="CENTER">
<buttons>
<Button id="btnPrevious" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="< Zurück" />
<Button id="btnNext" alignment="CENTER" contentDisplay="CENTER" defaultButton="true" mnemonicParsing="false" pickOnBounds="false" text="Weiter >" />
<Button id="btnFinish" alignment="CENTER" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="Fertigstellen" />
<Button id="btnCancel" alignment="CENTER" cancelButton="true" contentDisplay="CENTER" mnemonicParsing="false" pickOnBounds="false" text="Abbrechen" />
</buttons>
</ButtonBar>
</bottom>
<center>
<AnchorPane fx:id="taskPane" pickOnBounds="false" BorderPane.alignment="CENTER" />
</center>
</BorderPane>
logon.fxml(含fx:root)
<fx:root type="AnchorPane" xmlns="http://javafx.com/javafx/8.0.60" xmlns:fx="http://javafx.com/fxml/1">
<children>
<TitledPane alignment="TOP_LEFT" animated="false" collapsible="false" contentDisplay="CENTER" pickOnBounds="false" styleClass="taskPane" stylesheets="@application.css" text="Logon" AnchorPane.bottomAnchor="0.0" AnchorPane.leftAnchor="0.0" AnchorPane.rightAnchor="0.0" AnchorPane.topAnchor="0.0">
<font>
<Font name="System Bold" size="18.0" />
</font>
<content>
<GridPane maxHeight="150.0" maxWidth="250.0" pickOnBounds="false" styleClass="inputGrid">
<columnConstraints>
<ColumnConstraints hgrow="SOMETIMES" maxWidth="94.0" minWidth="10.0" prefWidth="58.0" />
<ColumnConstraints hgrow="SOMETIMES" maxWidth="142.0" minWidth="10.0" prefWidth="140.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>
<Label pickOnBounds="false" text="Mandant" />
<Label pickOnBounds="false" text="Benutzer" GridPane.rowIndex="1" />
<Label pickOnBounds="false" text="Kennwort" GridPane.rowIndex="2" />
<TextField id="fldMandant" fx:id="fldMandant" pickOnBounds="false" GridPane.columnIndex="1" />
<TextField fx:id="fldBenutzer" pickOnBounds="false" prefWidth="110.0" GridPane.columnIndex="1" GridPane.rowIndex="1" />
<TextField fx:id="fldKennwort" pickOnBounds="false" GridPane.columnIndex="1" GridPane.rowIndex="2" />
</children>
</GridPane>
</content>
</TitledPane>
</children>
</fx:root>
好的,所以这个问题是偶然的 recursion/loop。我执行的从 FXML 加载节点的代码在 initialize(URL, ResourceBundle)
方法中。现在,将新加载的 fxml 的控制器设置为 相同的 控制器对象,从创建它的地方 (loader.setController(this);
) 导致 initialize(URL, ResourceBundle)
-method 运行 并因此再次加载相同的 fxml 。这永远不会停止。
我的解决方案是删除 loader.setController(this);
调用并(更重要的是)将 fxml 本身中的控制器设置为某个 other 控制器。为了保持控制器之间的连接,我创建了一个名为 SubController
的接口。所有代表 step/task 而不是向导本身的控制器都实现了它。该接口指定了我要转发给 SubController 的四个 onButtonClick 方法。事件的实际处理现在发生在 SubController 中。
@FXML
void onCancel(ActionEvent event)
{
this.currentSub.onCancel(event);
}
@FXML
void onFinish(ActionEvent event)
{
this.currentSub.onFinish(event);
}
@FXML
void onNext(ActionEvent event)
{
this.currentSub.onNext(event);
}
@FXML
void onPrevious(ActionEvent event)
{
this.currentSub.onPrevious(event);
}