JavaFX - автоматизировать очистку Textarea (скользящая политика?) - PullRequest
0 голосов
/ 09 апреля 2019

У меня есть компонент Textarea, который используется для отображения сообщений, проходящих между двумя приложениями (точнее, сообщения HL7).Каждый раз, когда сообщение успешно обрабатывается, оно регистрируется, а также отправляется подтверждение от принимающей системы.Эти сообщения могут быть отправлены тысячами, и я чувствую, что неизбежно наступит момент, когда начнутся проблемы, когда эти компоненты «переполнятся».Я хотел бы реализовать стратегию опрокидывания, вроде log4j, где вы можете сказать, чтобы она сохраняла, скажем, только 10 файлов по 1 МБ.Я хотел бы иметь значение, которое пользователь может установить, и мой компонент (возможно, расширение компонента Textarea) автоматически сохранит только это количество строк и очистит первые при добавлении новых.Я относительно новичок в JavaFX (из Swing), я посмотрел на варианты, но не могу понять, как это сделать.

Спасибо

Ответы [ 2 ]

0 голосов
/ 10 апреля 2019

Я прошел на шаг выше принятого ответа (без которого я все еще пытался бы использовать 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;
    }
}
0 голосов
/ 10 апреля 2019

Как я уже упоминал в разделе комментариев этого вопроса, я рекомендую вам использовать ListView вместо TextArea. Это дает вам несколько преимуществ:

  1. ListView - это «виртуальный» элемент управления - он отображает только ячеек , чтобы заполнить видимое пространство, и ячейки используются повторно при прокрутке. Это позволяет иметь в ListView тысячи предметов без потери производительности.

  2. Модель ListView - это наблюдаемый список , который является гораздо лучшим способом представления отдельных сообщений, чем наличие одного гиганта String в TextArea. Когда добавление элемента в список приводит к тому, что он выходит за пределы некоторой произвольной емкости, вы можете просто удалить элемент (ы) из начала указанного списка (или конца, если вставляете элементы сверху, а не снизу).

  3. A ListView обеспечивает гораздо большую гибкость при отображении вашего сообщения. Это достигается с помощью пользовательской фабрики ячеек . Например, вы можете иметь определенные диапазоны сообщения разных цветов, используя 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);
            }
        });
    }

}
...