我正在研究一个处理多个fxml和相应控制器文件的项目。我需要以某种方式从 B.fxml 的控制器访问在 A.fxml 中定义的fxml元素,并使用它。
不允许显示实际代码。 但是,为此,我构建了一个简单的应用程序,其中包含两个FXML及其对应的控制器。
此应用程序具有带有ButtonController.java的Button.fxml和带有ProgressIndicatorController.java的ProgressIndicator.fxml
点击按钮后,进度指示器将变为活动状态。
下面是代码:
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方法。 但是,当我单击按钮时,进度指示器不会更新。
我也没有收到任何错误消息。
我碰到了这个链接Javafx - how to acces FXML "objects",虽然确实在很大程度上帮助了我,但我也无法完成这项工作。我只是尝试修改按钮单击方法,如下所示:
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元素)以某种方式起作用。
任何建议都是最欢迎的。经历了几个小时。 Stackoverflow似乎是不得已的方法。
编辑1:开始
事实证明,由于Zephyr的第一条评论中所述的原因,进度指示器未更新。因此,我为我的应用程序创建了一个separte线程,由于进度指示器已按预期进行更新,因此似乎工作正常。
成功更新进度指示器的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方法已成功执行。只是进度指示器根本没有更新。它始终处于“ 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:END
编辑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 Project 。
编辑2:结束
编辑3:开始
在 EDIT 1 部分下,尝试测试成功更新进度指示器的 onButton1Clicked()版本时,请不要忘记添加private Scene sceneProgressIndicator
作为 ButtonController.java 类的成员变量。
编辑3:END
答案 0 :(得分:1)
我假设您想要这样的东西(请注意注释):
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();
}
}