JavaFx TextArea 固定内容行数

Nee*_*eel 1 java javafx

我有一个固定TextArea的 50 行。如果内容达到第 50 行,则应删除第 1 行并添加第 51 行以保持固定行数。

此行为与应用程序控制台相同,后者在某个时间点后隐藏以前的输入。

目前我正在TextArea使用计数器清除后到达第 50 行。

public static void updateTextAreaTest(String text) {
    lineCount++;

    Platform.runLater(() -> {
        if (lineCount <= 50) {
            txtAreaTest.appendText(text + "\n");
        } else {
            txtAreaTest.setText("");
            lineCount = 0;
        }
    });
}
Run Code Online (Sandbox Code Playgroud)

我需要在添加新行时隐藏第一行,而不会影响运行了如此多线程的应用程序的性能。

编辑:
TextArea不可编辑。TextArea将在没有用户交互的情况下自动更新。

Jam*_*s_D 6

正如评论中所建议的, aListView可能是一个首选选项。

但是,如果要使用文本区域,可以通过TextFormatter在文本区域上设置 a 来实现。该filterTextFormatter可检查文本区域提出了新的文本行数,如果包含多个行的允许次数,修改改变下降的第一线。请注意,此解决方案允许在单个操作中插入多行文本。

import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javafx.animation.Animation;
import javafx.animation.KeyFrame;
import javafx.animation.Timeline;
import javafx.application.Application;
import javafx.scene.Scene;
import javafx.scene.control.TextArea;
import javafx.scene.control.TextFormatter;
import javafx.scene.layout.BorderPane;
import javafx.stage.Stage;
import javafx.util.Duration;


/**
 * JavaFX App
 */
public class App extends Application {

    private int lineNumber  ;
    private final int MAX_LINES = 50 ;

    private TextArea createConsole() {
        TextArea appConsole = new TextArea();
        appConsole.setWrapText(false);
        appConsole.setEditable(false);

        Pattern newline = Pattern.compile("\n");
        appConsole.setTextFormatter(new TextFormatter<String>(change ->  {

            String newText = change.getControlNewText();

            // count lines in proposed new text:
            Matcher matcher = newline.matcher(newText);
            int lines = 1 ;
            while (matcher.find()) lines++;

            // if there aren't too many lines just return the changed unmodified:
            if (lines <= MAX_LINES) return change ;

            // drop first (lines - 50) lines and replace all text
            // (there's no other way AFAIK to drop text at the beginning 
            // and replace it at the end):
            int linesToDrop = lines - MAX_LINES ;
            int index = 0 ; 
            for (int i = 0 ; i < linesToDrop ; i++) {
                index = newText.indexOf('\n', index) ;
            }
            change.setRange(0, change.getControlText().length());
            change.setText(newText.substring(index+1));

            return change  ;
        }));

        return appConsole;
    }

    @Override
    public void start(Stage stage) {

        TextArea appConsole = createConsole();

        // Fill with 45 lines to start:
        appConsole.appendText("Line 1");
        for (lineNumber = 2 ; lineNumber <= 45 ; lineNumber++) {
            appConsole.appendText("\nLine "+lineNumber);
        }

        // add a new line every 2 seconds:
        Timeline demo = new Timeline(
            new KeyFrame(Duration.seconds(2), 
                e -> appConsole.appendText("\nLine "+(lineNumber++))
            )
        );
        demo.setCycleCount(Animation.INDEFINITE);
        demo.play();

        stage.setScene(new Scene(new BorderPane(appConsole)));

        stage.show();
    }


    public static void main(String[] args) {
        launch();
    }

}
Run Code Online (Sandbox Code Playgroud)

这个解决方案的一个好处是它是文本区域的“即发即弃”配置。您创建文本区域,在其上设置格式化程序,它会自动提供永远不会超过 50 行文本的功能,如果需要,可以删除开头的行,然后其余代码只需调用TextArea方法(例如作为appendText()) 根据需要。