0

我已经阅读了有关此主题的 Stackoverflow 上的其他文章。但没有一个完全符合我的问题。

我想在 TextArea 中记录一个算法。在算法的每次迭代中,此 TextArea 中的文本应通过 appendText() 扩展。

我的第一个问题是:我应该在哪里创建新线程以及两个线程如何相互通信(GUI 和算法)?

在我的实际设计中,我有三个重要的类:包含 TextArea 的视图、调用算法的控制器和需要多次迭代的算法和 TextArea(在多个位置调用 appendText() 方法在代码中)。

在这个设计中,控制器调用算法,算法使用 for 循环迭代 n 次,在它终止后,GUI 显示更改。但我希望 GUI 在算法调用 appendText() 方法时同时显示更改。

我的第二个问题是TextArea 的自动滚动。在每次 appendText 调用之后,TextArea 应该完全向下滚动。但我认为这个问题的解决方案与我的第一个问题的解决方案相同。

我将非常感谢一些帮助。

4

1 回答 1

0

几乎不可能在没有(很多)更多信息的情况下完全回答您的问题,但我将使用的一般方法是让算法有一个回调来处理消息,该消息可以由算法的每个步骤调用。从控制器,传递一个回调的实现,它在 FX 应用程序线程上使用消息更新文本区域。

就像是:

public class Algorithm {

    private Consumer<String> statusCallback ;

    public Algorithm(Consumer<String> statusCallback) {
        this.statusCallback = statusCallback ;
    }

    public Algorithm() {
        // by default, callback does nothing:
        this(s -> {});
    }

    public void performAlgorithm() {

        while (! finished() ) {
            doNextStep();
            String statusMessage = getStatus();
            statusCallback.accept(statusMessage);
        }
    }
}

接着

public class Controller {

    private View view = ... ;

    public void startAlgorithm() {
        Algorithm algorithm = new Algorithm(s -> Platform.runLater(view.appendStatus(s)));
        Thread t = new Thread(algorithm::performAlgorithm);
        t.setDaemon(true);
        t.start();
    }
}

然后,您View可以执行以下操作(请注意,您可以使用 向下滚动textArea.setScrollTop(Double.MAX_VALUE);):

public class View {
    private TextArea textArea ;

    public View() {
        textArea = new TextArea();
        // ...
    }

    public void appendStatus(String status) {
        if (!textArea.getText().isEmpty()) {
            textArea.appendText("\n");
        }
        textArea.appendText(status);
        textArea.setScrollTop(Double.MAX_VALUE);
    }
}

只要您的算法不会太快地创建太多状态更新(这样它们会淹没 FX 应用程序线程并阻止其正常工作),这应该可以工作。

于 2016-07-29T18:56:24.340 回答