JavaFX-自动清除Textarea(滚动策略?)

时间:2019-04-09 18:38:46

标签: javafx textarea limit

我有一个Textarea组件,用于显示2个应用程序之间传递的消息(确切地说是HL7消息)。每次成功处理一条消息时,都会记录该消息以及从接收系统发回的确认。这些消息可以成千上万个发送,我感觉不可避免地会出现一个问题,即当该组件“溢出”时,问题就会开始发生。我想实现一个过渡策略,有点像log4j,在其中您可以告诉它仅保留10个1MB的文件。我希望有一个用户可以设置的值,而我的组件(也许是Textarea组件的扩展)将仅自动保留该行数,并在添加新行时清除第一个行。我对JavaFX相对较新(来自Swing),我研究了这些选项,但无法完全弄清楚如何做到这一点。

谢谢

2 个答案:

答案 0 :(得分:0)

正如我在问题的评论部分中提到的那样,建议您使用ListView而不是TextArea。这会给您带来一些好处:

  1. ListView是一个“虚拟”控件-它仅呈现足够的cells来填充可见空间,并且在滚动时可重复使用单元格。这样一来,ListView中就可以拥有数千个项目,而不会影响性能。

  2. ListView的模型为an observable list,与在String中包含一个巨型TextArea相比,这是表示独立消息的一种更好的方法。当将元素添加到列表中导致其超出任意容量时,您可以简单地从列表的开头(或末尾,如果在顶部而不是底部插入项目)中删除一个项目。

  3. ListView在显示消息时提供了更大的灵活性。这是通过自定义cell factory完成的。例如,通过使用TextFlow作为ListCell的图形,可以使消息的某些范围具有不同的颜色。但是,请务必阅读Cell.updateItem(Object,boolean)的文档,因为您必须正确覆盖该方法。否则,由于单元被重用,可能导致伪像。

一个简单的例子:

import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Consumer;
import javafx.animation.PauseTransition;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.ListView;
import javafx.stage.Stage;
import javafx.util.Duration;

public class Main extends Application {

    private static void generateMessages(Consumer<String> onNewMessage) {
        AtomicInteger counter = new AtomicInteger();
        PauseTransition pt = new PauseTransition(Duration.seconds(1));
        pt.setOnFinished(e -> {
            onNewMessage.accept(String.format("Message #%,d", counter.incrementAndGet()));
            pt.playFromStart();
        });
        pt.playFromStart();
    }

    @Override
    public void start(Stage primaryStage) {
        ListView<String> listView = new ListView<>();
        primaryStage.setScene(new Scene(listView, 500, 300));
        primaryStage.show();

        generateMessages(message -> {
            listView.getItems().add(message);
            if (listView.getItems().size() > 10) {
                listView.getItems().remove(0);
            }
        });
    }

}

答案 1 :(得分:0)

我在可接受的答案之上走了一步(没有这个答案,我仍然会尝试使用TextArea!)并构建了这个自定义组件(是的,有一个空的catch块,但是我有一个清晰的日志按钮,当日志为空,请处理:))

public class HL7ListView extends ListView<String>
{
    private int serviceLogMaxEntries;

    public HL7ListView() 
    {
        super();

        getItems().addListener((ListChangeListener<String>) listener ->
        {
            if (getItems().size() > serviceLogMaxEntries)
            {
                Platform.runLater(() -> 
                {
                    try
                    {
                        getItems().remove(0);
                    }
                    catch (Exception ex)
                    {}
                });
            }
        });
    }

    public void setServiceLogMaxEntries(int serviceLogMaxEntries)
    {
        this.serviceLogMaxEntries = serviceLogMaxEntries;
    }
}