如何从其他类获取对该节点的引用?

时间:2018-05-07 14:18:17

标签: java javafx

有没有简单的方法可以从其他类获得对舞台控制的引用?除了Delphi之外,它似乎是每个基于GUI的框架中的问题。如果只有ControllerMain类是静态的......

这是我的代码:

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

2 个答案:

答案 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))));
}