Я работаю над проектом, который имеет дело с несколькими 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: КОНЕЦ