我有一个Textarea组件,用于显示两个应用程序之间的消息(确切地说是HL7消息)。每次成功处理消息时,都会记录消息以及从接收系统发回的确认。这些消息可以由成千上万的人发送,我觉得当这些组件“溢出”时,问题将不可避免地发生。我想实现一个翻转策略,有点像log4j,你可以告诉它只保留10个1MB的文件。我希望有一个用户可以设置的值,我的组件(可能是Textarea组件的扩展)将自动保留该行数,并在添加新行时清除第一行。我是相对较新的JavaFX(来自Swing),我已经查看了选项,但无法弄清楚如何做到这一点。
谢谢
正如我在问题的评论部分提到的,我建议你使用ListView
而不是TextArea
。这给您带来了一些好处:
ListView
是一个“虚拟”控件 - 它只渲染足够的cells来填充可见空间,并且在滚动时重复使用单元格。这允许人们在ListView
中拥有数千个项目而不会使性能受到影响。ListView
的模型是an observable list,这是一种更好的方式来表示单独的消息,而不是在String
中有一个巨大的TextArea
。向列表中添加元素会使其增长超过任意容量时,您只需从所述列表的开头删除一个项目(如果在顶部而不是底部插入项目,则结束)。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);
}
});
}
}
我超越了接受的答案(没有它我仍然会尝试使用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;
}
}