Reputation: 465
Is there any simple way to get a reference to control of a stage from other class? It seems to be a problem in every GUI based framework except Delphi. If only Controller
or Main
class were static...
Here is my code:
Controller.java:
package sample;
import javafx.fxml.*;
import javafx.scene.control.Button;
import javafx.scene.control.TextArea;
public class Controller {
@FXML
private Button algorithms;
@FXML
private Button settings;
@FXML
private Button run;
@FXML
public TextArea console; // I want access that node from class named 'Utils'
@FXML
void initialize() { }
public Controller () { }
@FXML
private void onRun() {
Utility.get().runBench();
}
@FXML
private void onSettings() {
console.appendText("I am opening settings...");
}
@FXML
private void onAlgorithm() {
console.appendText("I am opening list of Algorithms...");
}
}
Utils.java:
package sample;
import sample.Algorithms.BubbleSort;
import java.util.*;
// Singleton
public class Utility {
private static Utility ourInstance = new Utility();
public static Utility get() {
return ourInstance;
}
private Utility() {
listOfAlgorithms.add(new BubbleSort(howManyN));
}
List<Algorithm> listOfAlgorithms = new LinkedList<>();
Long howManyN = 999L;
public void runBench() {
for (Algorithm a: listOfAlgorithms) {
double start = System.nanoTime();
a.run();
double end = System.nanoTime();
double result = end - start;
System.out.println(
// console.appendText( // Accessing like that would be ideal
"Algorithm: " + a.getClass().getName() + "\n" +
"For N = " + a.getN() + " time is: " + result
);
}
}
}
I heard about FXMLoader, but it is in Main
Class, so there is no difference.
Main.java:
package sample;
import javafx.application.Application;
import javafx.fxml.FXMLLoader;
import javafx.scene.Parent;
import javafx.scene.Scene;
import javafx.stage.Stage;
public class Main extends Application {
final String APP_NAME = "SortAll 2";
final String RES_PATH = "../resources/scene.fxml";
public static void main(String[] args) {
launch(args);
}
@Override
public void start(Stage primaryStage) throws Exception{
Parent root = FXMLLoader.load(getClass().getResource(RES_PATH));
primaryStage.setTitle(APP_NAME);
primaryStage.setScene(new Scene(root));
primaryStage.show();
}
}
Upvotes: 0
Views: 1012
Reputation: 209553
Pass an object to the runBench()
method that describes what you want to do with the result. Since you're encapsulating the result as a String
, you could use a Consumer<String>
:
public void runBench(Consumer<String> onAlgorithmCompletion) {
for (Algorithm a: listOfAlgorithms) {
double start = System.nanoTime();
a.run();
double end = System.nanoTime();
double result = end - start;
onAlgorithmCompletion.accept(
"Algorithm: " + a.getClass().getName() + "\n" +
"For N = " + a.getN() + " time is: " + result
);
}
}
Then from your controller you can do
@FXML
private void onRun() {
Utility.get().runBench(console::appendText);
}
This is unrelated to the question you posted, but you almost certainly need to execute your runBench()
method in a background thread, since it apparently takes some time to execute. If you do that, you need to ensure that the console is only accessed on the FX Application Thread. The above solution is easy to modify to do this (your runBench(...)
method doesn't need to change at all):
private Executor exec = Executors.newCachedThreadPool();
// ...
@FXML
private void onRun() {
exec.execute(() -> Utility.get().runBench(
result -> Platform.runLater(console.appendText(result))));
}
Upvotes: 2
Reputation: 405
Umm, can't you just pass console as a runBench() parameter?
Utility.java:
public void runBench(TextArea console) {
for (Algorithm a: listOfAlgorithms) {
double start = System.nanoTime();
a.run();
double end = System.nanoTime();
double result = end - start;
System.out.println(
console.appendText(
"Algorithm: " + a.getClass().getName() + "\n" +
"For N = " + a.getN() + " time is: " + result
);
}
}
and
Controller.java:
@FXML
private void onRun() {
Utility.get().runBench(console);
}
Upvotes: 2