无法通过另一个控制器控制另一个 fxml 文件的元素
Unable to control elements of another fxml file through another controller
我正在处理一个处理多个 fxml 和相应控制器文件的项目。我需要以某种方式从 B.fxml 的控制器访问 A.fxml 中定义的 fxml 元素并使用它.
不允许我显示实际代码。
但是,为此目的,我构建了一个简单的应用程序,其中包含两个 FXML 及其相应的控制器。
此应用程序有 Button.fxml 和 ButtonController.java 以及 ProgressIndicator.fxml 和 ProgressIndicatorController.java
单击该按钮后,进度指示器会亮起。
下面是代码:
Button.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ButtonController">
<children>
<Pane prefHeight="206.0" prefWidth="281.0">
<children>
<Button fx:id="button1" layoutX="59.0" layoutY="63.0" mnemonicParsing="false" prefHeight="63.0" prefWidth="164.0" text="Button" onAction="#onButton1Clicked" />
</children>
</Pane>
</children>
</AnchorPane>
ButtonController.java
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ButtonController implements Initializable{
@FXML
private Button button1;
private ProgressIndicator progressIndicator;
private ProgressIndicatorController progressIndicatorController;
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
Object loader = FXMLLoader.load(getClass().getResource("ProgressIndicator.fxml"));
Scene sceneProgressIndicator = new Scene((Parent) loader, 1400, 800);
sceneProgressIndicator.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
sceneProgressIndicator.setFill(Color.TRANSPARENT);
Stage primaryStageProgressIndicator = new Stage();
primaryStageProgressIndicator.setScene(sceneProgressIndicator);
primaryStageProgressIndicator.setResizable(false);
primaryStageProgressIndicator.setHeight(311);
primaryStageProgressIndicator.setWidth(523);
primaryStageProgressIndicator.show();
} catch (IOException e) {
e.printStackTrace();
}
// TODO Auto-generated method stub
}
public void onButton1Clicked() {
FXMLLoader fxmlLoaderProgressIndicator = new FXMLLoader();
fxmlLoaderProgressIndicator.setLocation(getClass().getResource("ProgressIndicator.fxml"));
try {
Parent root = fxmlLoaderProgressIndicator.load();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressIndicatorController = (ProgressIndicatorController) fxmlLoaderProgressIndicator.getController();
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
progressIndicator = progressIndicatorController.getProgressIndicator1();
progressIndicator.setProgress(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
ProgressIndicator.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ProgressIndicatorController">
<children>
<Pane prefHeight="200.0" prefWidth="200.0">
<children>
<ProgressIndicator fx:id="progressIndicator1" layoutX="47.0" layoutY="31.0" prefHeight="103.0" prefWidth="106.0" progress="0.0" />
</children>
</Pane>
</children>
</AnchorPane>
ProgressindicatorController.java
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ProgressIndicatorController implements Initializable {
@FXML
private ProgressIndicator progressIndicator1;
@Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public ProgressIndicator getProgressIndicator1() {
System.out.println("getteeerrrrrrrr");
return progressIndicator1;
}
public void setProgressIndicator1(ProgressIndicator progressIndicator1) {
this.progressIndicator1 = progressIndicator1;
}
}
getter方法调用成功。
但是,当我单击按钮时,进度指示器不会更新。
我也没有收到任何类型的错误消息。
我遇到了这个 link 这确实在很大程度上帮助了我,但我也无法完成这项工作。我只是尝试修改按钮点击方法如下:
onButton1Cliked()
public void onButton1Clicked() {
progressIndicator = (ProgressIndicator) sceneProgressIndicator.lookup("#progressIndicator1");
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
点击按钮确实会打印出语句。但是进度指示器不会随着每次 for 循环迭代而更新。进度指示器终于更新并显示完成。
知道为什么会这样吗?
除了使用查找方法之外,还有其他方法可以访问 fxml 元素。我以前的方法(试图通过控制器获取 fxml 元素)是否可以以某种方式工作。
欢迎提出任何意见或建议。进入这个几个小时。 Whosebug 似乎是最后的手段。
编辑 1:开始
事实证明,由于 Zephyr 第一条评论中解释的原因,进度指示器没有更新。所以我为我的应用程序创建了一个单独的线程,它似乎工作正常,因为进度指示器已按预期更新。
成功更新进度指示器的 onButton1Clicked() 方法的工作版本:
public void onButton1Clicked() {
progressIndicator = (ProgressIndicator) sceneProgressIndicator.lookup("#progressIndicator1");
Runnable runnable = new Runnable() {
@Override
public void run() {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
解决了这个线程问题后,我再次尝试按照我的 OP 中提到的原始方式进行(即获取 ProgressIndicatorController 实例并访问其进度指示器,然后尝试更新它)。但是,这对我不起作用。我尝试调试并发现我正在取回 ProgressIndicatorController 和 ProgressIndicator 实例。
如果我的代码持有进度指示器实例,那么为什么我的代码无法更新进度指示器。
println 方法被执行 successfully.Its 只是在 all.It 处未更新的进度指示器一直处于“0”。
不更新 progressIndicator 的 onButton1Clicked() 方法版本:
public void onButton1Clicked() {
FXMLLoader fxmlLoaderProgressIndicator = new FXMLLoader();
fxmlLoaderProgressIndicator.setLocation(getClass().getResource("ProgressIndicator.fxml"));
try {
Parent root = fxmlLoaderProgressIndicator.load();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressIndicatorController = (ProgressIndicatorController) fxmlLoaderProgressIndicator.getController();
progressIndicator = progressIndicatorController.getProgressIndicator1();
Runnable runnable = new Runnable() {
@Override
public void run() {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
编辑 1:结束
编辑 2:开始
正在添加 运行 此示例应用程序所需的其他文件
Main.java
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
Object root =FXMLLoader.load(getClass().getResource("Button.fxml"));
Scene scene = new Scene((Parent) root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
我的 application.css 文件中没有任何内容。它是空的。
我在 Java 8 上使用 JavaFX8。 IDE 是 Eclipse Photon
我使用 e(fx)clipse 插件创建了我的项目,并从创建新项目中选择 JavaFX 项目 window.
编辑 2:结束
编辑 3:开始
在 EDIT 1 部分下尝试测试成功更新进度指示器的 onButton1Clicked() 版本时请不要忘记包含 private Scene sceneProgressIndicator
作为 class ButtonController.java.
的成员变量
编辑 3:结束
我假设你想要这样的东西(注意评论):
import java.io.IOException;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ButtonController {
@FXML
private Button button1;
private ProgressIndicator progressIndicator;
private Scene sceneProgressIndicator;
@FXML
public void initialize() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ProgressIndicator.fxml"));
Pane progressIndicatorPane = loader.load();
ProgressIndicatorController progressIndicatorController = loader.getController(); //get a reference to the progress indicator controller
progressIndicator = progressIndicatorController.getProgressIndicator1(); //get the progress indicator
sceneProgressIndicator = new Scene(progressIndicatorPane, 1400, 800);
sceneProgressIndicator.setFill(Color.TRANSPARENT);
Stage primaryStageProgressIndicator = new Stage();
primaryStageProgressIndicator.setScene(sceneProgressIndicator);
primaryStageProgressIndicator.setResizable(false);
primaryStageProgressIndicator.setHeight(311);
primaryStageProgressIndicator.setWidth(523);
primaryStageProgressIndicator.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onButton1Clicked() {
Runnable runnable = () -> {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
final double fD = i;
Platform.runLater(() -> progressIndicator.setProgress(fD));//update done on javafx thread
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}
我正在处理一个处理多个 fxml 和相应控制器文件的项目。我需要以某种方式从 B.fxml 的控制器访问 A.fxml 中定义的 fxml 元素并使用它.
不允许我显示实际代码。 但是,为此目的,我构建了一个简单的应用程序,其中包含两个 FXML 及其相应的控制器。
此应用程序有 Button.fxml 和 ButtonController.java 以及 ProgressIndicator.fxml 和 ProgressIndicatorController.java
单击该按钮后,进度指示器会亮起。
下面是代码:
Button.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.Button?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ButtonController">
<children>
<Pane prefHeight="206.0" prefWidth="281.0">
<children>
<Button fx:id="button1" layoutX="59.0" layoutY="63.0" mnemonicParsing="false" prefHeight="63.0" prefWidth="164.0" text="Button" onAction="#onButton1Clicked" />
</children>
</Pane>
</children>
</AnchorPane>
ButtonController.java
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ButtonController implements Initializable{
@FXML
private Button button1;
private ProgressIndicator progressIndicator;
private ProgressIndicatorController progressIndicatorController;
@Override
public void initialize(URL location, ResourceBundle resources) {
try {
Object loader = FXMLLoader.load(getClass().getResource("ProgressIndicator.fxml"));
Scene sceneProgressIndicator = new Scene((Parent) loader, 1400, 800);
sceneProgressIndicator.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
sceneProgressIndicator.setFill(Color.TRANSPARENT);
Stage primaryStageProgressIndicator = new Stage();
primaryStageProgressIndicator.setScene(sceneProgressIndicator);
primaryStageProgressIndicator.setResizable(false);
primaryStageProgressIndicator.setHeight(311);
primaryStageProgressIndicator.setWidth(523);
primaryStageProgressIndicator.show();
} catch (IOException e) {
e.printStackTrace();
}
// TODO Auto-generated method stub
}
public void onButton1Clicked() {
FXMLLoader fxmlLoaderProgressIndicator = new FXMLLoader();
fxmlLoaderProgressIndicator.setLocation(getClass().getResource("ProgressIndicator.fxml"));
try {
Parent root = fxmlLoaderProgressIndicator.load();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressIndicatorController = (ProgressIndicatorController) fxmlLoaderProgressIndicator.getController();
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
progressIndicator = progressIndicatorController.getProgressIndicator1();
progressIndicator.setProgress(i);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
ProgressIndicator.fxml
<?xml version="1.0" encoding="UTF-8"?>
<?import javafx.scene.control.ProgressIndicator?>
<?import javafx.scene.layout.AnchorPane?>
<?import javafx.scene.layout.Pane?>
<AnchorPane xmlns="http://javafx.com/javafx/8.0.171" xmlns:fx="http://javafx.com/fxml/1" fx:controller="application.ProgressIndicatorController">
<children>
<Pane prefHeight="200.0" prefWidth="200.0">
<children>
<ProgressIndicator fx:id="progressIndicator1" layoutX="47.0" layoutY="31.0" prefHeight="103.0" prefWidth="106.0" progress="0.0" />
</children>
</Pane>
</children>
</AnchorPane>
ProgressindicatorController.java
package application;
import java.io.IOException;
import java.net.URL;
import java.util.ResourceBundle;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.fxml.Initializable;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.image.Image;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ProgressIndicatorController implements Initializable {
@FXML
private ProgressIndicator progressIndicator1;
@Override
public void initialize(URL location, ResourceBundle resources) {
// TODO Auto-generated method stub
}
public ProgressIndicator getProgressIndicator1() {
System.out.println("getteeerrrrrrrr");
return progressIndicator1;
}
public void setProgressIndicator1(ProgressIndicator progressIndicator1) {
this.progressIndicator1 = progressIndicator1;
}
}
getter方法调用成功。 但是,当我单击按钮时,进度指示器不会更新。
我也没有收到任何类型的错误消息。
我遇到了这个 link
onButton1Cliked()
public void onButton1Clicked() {
progressIndicator = (ProgressIndicator) sceneProgressIndicator.lookup("#progressIndicator1");
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
点击按钮确实会打印出语句。但是进度指示器不会随着每次 for 循环迭代而更新。进度指示器终于更新并显示完成。
知道为什么会这样吗?
除了使用查找方法之外,还有其他方法可以访问 fxml 元素。我以前的方法(试图通过控制器获取 fxml 元素)是否可以以某种方式工作。
欢迎提出任何意见或建议。进入这个几个小时。 Whosebug 似乎是最后的手段。
编辑 1:开始
事实证明,由于 Zephyr 第一条评论中解释的原因,进度指示器没有更新。所以我为我的应用程序创建了一个单独的线程,它似乎工作正常,因为进度指示器已按预期更新。
成功更新进度指示器的 onButton1Clicked() 方法的工作版本:
public void onButton1Clicked() {
progressIndicator = (ProgressIndicator) sceneProgressIndicator.lookup("#progressIndicator1");
Runnable runnable = new Runnable() {
@Override
public void run() {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
解决了这个线程问题后,我再次尝试按照我的 OP 中提到的原始方式进行(即获取 ProgressIndicatorController 实例并访问其进度指示器,然后尝试更新它)。但是,这对我不起作用。我尝试调试并发现我正在取回 ProgressIndicatorController 和 ProgressIndicator 实例。
如果我的代码持有进度指示器实例,那么为什么我的代码无法更新进度指示器。 println 方法被执行 successfully.Its 只是在 all.It 处未更新的进度指示器一直处于“0”。
不更新 progressIndicator 的 onButton1Clicked() 方法版本:
public void onButton1Clicked() {
FXMLLoader fxmlLoaderProgressIndicator = new FXMLLoader();
fxmlLoaderProgressIndicator.setLocation(getClass().getResource("ProgressIndicator.fxml"));
try {
Parent root = fxmlLoaderProgressIndicator.load();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
progressIndicatorController = (ProgressIndicatorController) fxmlLoaderProgressIndicator.getController();
progressIndicator = progressIndicatorController.getProgressIndicator1();
Runnable runnable = new Runnable() {
@Override
public void run() {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
try {
System.out.println("Progressingggg " + i);
progressIndicator.setProgress(i);
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
编辑 1:结束
编辑 2:开始
正在添加 运行 此示例应用程序所需的其他文件
Main.java
package application;
import javafx.application.Application;
import javafx.stage.Stage;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.scene.layout.BorderPane;
import javafx.fxml.FXMLLoader;
public class Main extends Application {
@Override
public void start(Stage primaryStage) {
try {
Object root =FXMLLoader.load(getClass().getResource("Button.fxml"));
Scene scene = new Scene((Parent) root,400,400);
scene.getStylesheets().add(getClass().getResource("application.css").toExternalForm());
primaryStage.setScene(scene);
primaryStage.show();
} catch(Exception e) {
e.printStackTrace();
}
}
public static void main(String[] args) {
launch(args);
}
}
我的 application.css 文件中没有任何内容。它是空的。
我在 Java 8 上使用 JavaFX8。 IDE 是 Eclipse Photon
我使用 e(fx)clipse 插件创建了我的项目,并从创建新项目中选择 JavaFX 项目 window.
编辑 2:结束
编辑 3:开始
在 EDIT 1 部分下尝试测试成功更新进度指示器的 onButton1Clicked() 版本时请不要忘记包含 private Scene sceneProgressIndicator
作为 class ButtonController.java.
编辑 3:结束
我假设你想要这样的东西(注意评论):
import java.io.IOException;
import javafx.application.Platform;
import javafx.fxml.FXML;
import javafx.fxml.FXMLLoader;
import javafx.scene.Scene;
import javafx.scene.control.Button;
import javafx.scene.control.ProgressIndicator;
import javafx.scene.layout.Pane;
import javafx.scene.paint.Color;
import javafx.stage.Stage;
public class ButtonController {
@FXML
private Button button1;
private ProgressIndicator progressIndicator;
private Scene sceneProgressIndicator;
@FXML
public void initialize() {
try {
FXMLLoader loader = new FXMLLoader(getClass().getResource("ProgressIndicator.fxml"));
Pane progressIndicatorPane = loader.load();
ProgressIndicatorController progressIndicatorController = loader.getController(); //get a reference to the progress indicator controller
progressIndicator = progressIndicatorController.getProgressIndicator1(); //get the progress indicator
sceneProgressIndicator = new Scene(progressIndicatorPane, 1400, 800);
sceneProgressIndicator.setFill(Color.TRANSPARENT);
Stage primaryStageProgressIndicator = new Stage();
primaryStageProgressIndicator.setScene(sceneProgressIndicator);
primaryStageProgressIndicator.setResizable(false);
primaryStageProgressIndicator.setHeight(311);
primaryStageProgressIndicator.setWidth(523);
primaryStageProgressIndicator.show();
} catch (IOException e) {
e.printStackTrace();
}
}
public void onButton1Clicked() {
Runnable runnable = () -> {
for(double i = 0.0; i <= 1.0 ; i+=0.2) {
final double fD = i;
Platform.runLater(() -> progressIndicator.setProgress(fD));//update done on javafx thread
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
};
Thread thread = new Thread(runnable);
thread.start();
}
}