无法通过另一个控制器控制另一个fxml文件的元素 [英] Unable to control elements of another fxml file through another controller

查看:64
本文介绍了无法通过另一个控制器控制另一个fxml文件的元素的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在从事一个处理多个fxml和相应控制器文件的项目.我需要以某种方式从 B.fxml 的控制器访问在 A.fxml 中定义的fxml元素,并使用它.

I am working on a project which deals with multiple fxml and corresponding controller files. I need to somehow get access to an fxml element defined in say A.fxml from the controller of B.fxml and use it.

不允许显示实际代码. 但是,为此,我用两个FXML及其对应的控制器构建了一个简单的应用程序.

I am not allowed to show the actual code. However, for this purpose, I have built a simple application with two FXMLs and their corresponding controllers.

此应用程序具有带有ButtonController.java的Button.fxml和带有ProgressIndicatorController.java的ProgressIndicator.fxml

This application has Button.fxml with ButtonController.java and ProgressIndicator.fxml with ProgressIndicatorController.java

点击按钮后,进度指示器将变为活动状态.

Upon clicking the button, the Progress indicator would come live.

下面是代码:

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方法. 但是,当我单击按钮时,进度指示器不会更新.

The getter method is successfully called. However when I click the button, the progress indicator doesnot get updated.

我也没有收到任何错误消息.

I am also not getting any kind of error messages .

我碰到了此链接 Javafx-如何访问FXML对象"

I came across this link Javafx - how to acces FXML "objects" which indeed helped me to a great extent,but I'm not able to get this work too. I just tried to modify the button click method as follows :

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循环迭代而更新.进度指示器直到最后才更新并显示完成.

Clicking on the button does indeed print out the statements. But the progress indicator doesn't get updated with each for loop iteration. Its only at last that the progress indicator gets updated and shows done.

知道为什么会这样吗?

除了使用查找方法外,还有其他方法可以访问fxml元素.可以使我以前的方法(试图通过控制器获取fxml元素)以某种方式起作用.

Also is there any other way to access the fxml elements other than using a lookup method. Can my previous approach(trying to get the fxml elements through controller) be made to work somehow.

任何意见或建议都非常欢迎.经历了几个小时. Stackoverflow似乎是不得已的方法.

Any advice or suggestions are most welcome. Been into this for several hours. Stackoverflow seems to be the last resort.

开始

事实证明,由于Zephyr的第一条评论中所述的原因,进度指示器未更新.因此,我为我的应用程序创建了一个separte线程,由于进度指示器已按预期进行更新,因此看起来工作正常.

It turned out that the progress Indicator was not updating because of the reason explained in Zephyr's first comment. So i created a separte thread for my application and that seemed to work fine as the progress indicator got updated as expected.

成功更新进度指示器的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实例.

Having resolved this threading issue, I tried once again to go by the original way mentioned in my OP(i.e. to get the ProgressIndicatorController instance and access its progress indicator and then try updating it). However, this is not working for me. I tried debugging and found that I am getting back the ProgressIndicatorController and ProgressIndicator instance back.

为什么我的代码无法控制进度指示器实例,所以无法更新进度指示器. println方法已成功执行.只是进度指示器根本没有更新.它始终处于"0".

Why then my code is unable to update the progress indicator if it has a hold on the progress indicator instance. The println methods are executed successfully.Its just the progress indicator not getting updated at all.It stands at "0" all the time.

不更新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();

    }

END

开始

添加运行此示例应用程序所需的其他文件

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 文件中没有任何内容.它是空的.

My application.css file has nothing in it. Its empty.

我正在 Java 8 上使用 JavaFX8 . IDE是 Eclipse Photon

I'm using JavaFX8 on Java 8. IDE is Eclipse Photon

我使用 e(fx)clipse 插件创建了我的项目,并从创建新项目窗口中选择了 JavaFX Project .

I created my project using e(fx)clipse plugin and choosing JavaFX Project from create new project window.

END

开始

EDIT 1 部分下,尝试测试成功更新进度指示器的 onButton1Clicked()版本时,请不要忘记将private Scene sceneProgressIndicator作为类 ButtonController.java 的成员变量.

Under the section EDIT 1 while trying to test the version of onButton1Clicked() that successfully updates the progress indicator please don't forget to include private Scene sceneProgressIndicator as the member variable of the class ButtonController.java.

END

推荐答案

我假设您想要这样的东西(请注意注释):

I assume you wanted something like this (note the comments):

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文件的元素的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆