Невозможно управлять элементами другого файла fxml через другой контроллер - PullRequest
0 голосов
/ 07 июня 2019

Я работаю над проектом, который имеет дело с несколькими fxml и соответствующими файлами контроллера.Мне нужно каким-то образом получить доступ к элементу fxml, определенному, скажем, A.fxml из контроллера B.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;
    }

}

Метод получателя успешно вызван.Однако, когда я нажимаю кнопку, индикатор прогресса не обновляется.

Я также не получаю никаких сообщений об ошибках.

Я наткнулся на эту ссылку Javafx - как получить доступFXML "объекты" , которые действительно мне очень помогли, но я тоже не могу получить эту работу.Я просто попытался изменить метод нажатия кнопки следующим образом:

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();
            }
        }

    }

Нажатие на кнопку действительно распечатывает операторы.Но индикатор прогресса не обновляется при каждой итерации цикла.Только наконец индикатор прогресса обновляется и показывает готово.

Есть идеи, почему это происходит?

Также есть ли другой способ доступа к элементам fxml, кроме использования метода поиска,Может ли мой предыдущий подход (попытка получить элементы fxml через контроллер) как-то работать.

Любые советы или предложения приветствуются.Занимался этим несколько часов.Похоже, что переполнение стека является последним средством.

РЕДАКТИРОВАТЬ 1: НАЧАЛО

Оказалось, что индикатор прогресса не обновлялся по причине, описанной в первом комментарии Зефира.Поэтому я создал отдельную ветку для своего приложения, и она, кажется, работала нормально, так как индикатор прогресса обновлялся, как и ожидалось.

Рабочая версия метода 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».

Версия метода onButton1Clicked (), который НЕ обновляет progressIndicator:

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 файл не содержит ничего.Он пуст.

Я использую JavaFX8 на Java 8 .IDE - это Eclipse Photon

Я создал свой проект, используя плагин e (fx) clipse и выбрав JavaFX Project из окна создания нового проекта.

РЕДАКТИРОВАТЬ 2: КОНЕЦ

РЕДАКТИРОВАТЬ 3: СТАРТ

В разделе РЕДАКТИРОВАТЬ 1 при попытке протестировать версию onButton1Clicked () , которая успешно обновляет индикатор прогресса, пожалуйста, не забудьте включить private Scene sceneProgressIndicator в качестве переменной-членакласса ButtonController.java .

РЕДАКТИРОВАТЬ 3: КОНЕЦ

1 Ответ

1 голос
/ 09 июня 2019

Я полагаю, вы хотели что-то вроде этого (обратите внимание на комментарии):

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();
    }
}
...