有没有简单的方法可以从其他类获得对舞台控制的引用?除了Delphi之外,它似乎是每个基于GUI的框架中的问题。如果只有Controller
或Main
类是静态的......
这是我的代码:
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
);
}
}
}
我听说过FXMLoader,但它在Main
类,所以没有区别。
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();
}
}
答案 0 :(得分:2)
嗯,你不能把控制台作为runBench()参数传递吗?
<强> 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
);
}
}
和
<强> Controller.java 强>:
@FXML
private void onRun() {
Utility.get().runBench(console);
}
答案 1 :(得分:2)
将对象传递给描述您要对结果执行的操作的runBench()
方法。由于您将结果封装为String
,因此您可以使用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
);
}
}
然后从你的控制器你可以做
@FXML
private void onRun() {
Utility.get().runBench(console::appendText);
}
这与您发布的问题无关,但您几乎肯定需要在后台线程中执行runBench()
方法,因为它显然需要一些时间才能执行。如果这样做,则需要确保仅在FX Application Thread上访问控制台。上述解决方案很容易修改(您的runBench(...)
方法根本不需要更改):
private Executor exec = Executors.newCachedThreadPool();
// ...
@FXML
private void onRun() {
exec.execute(() -> Utility.get().runBench(
result -> Platform.runLater(console.appendText(result))));
}