Как получить ссылку на узел из другого класса? - PullRequest
0 голосов
/ 07 мая 2018

Есть ли какой-нибудь простой способ получить ссылку на управление сценой из другого класса? Кажется, это проблема во всех основах GUI, кроме Delphi. Если бы только 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 Class, так что нет никакой разницы.

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 голосов
/ 07 мая 2018

Передайте объект в метод 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. Приведенное выше решение легко изменить, чтобы сделать это (ваш runBench(...) метод вообще не нуждается в изменении):

private Executor exec = Executors.newCachedThreadPool();

// ...

@FXML
private void onRun() {
    exec.execute(() -> Utility.get().runBench(
        result -> Platform.runLater(console.appendText(result))));
}
0 голосов
/ 07 мая 2018

Хмм, разве вы не можете просто передать консоль в качестве параметра 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);
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...