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