首页 > 解决方案 > 将巨大的文本缓冲区加载到 QPlainTextEdit

问题描述

在小部件中显示巨大文本缓冲区的正确最佳QPlainTextEdit方法是什么?我的意思是监听滚动条移动事件,并根据当前滚动条位置仅动态地将文本的可见部分传递给小部件。

我无法将整个缓冲区发送到使用的小部件,setPlainText因为文本缓冲区的大小超过 1 GB,并且该函数需要它的副本,这会使内存使用量加倍。

标签: c++qt

解决方案


假设您有 1GB 数据并且您不想超过此内存负载,我认为您应该逐部分读取数据并将它们附加到QPlainTextEdit's 缓冲区。这样,您的大文本永远不会超过 1GB 的内存使用量。
实际上,用于存储加载部分的临时变量将在每次迭代时被删除,您只需在循环结束时将其销毁。

此外,如果您只想以不同的方式为可见部分着色(正如您在我们的讨论中所说),我认为您应该为整个文本着色,因为只会显示可见部分的颜色(因为其他部分是隐藏的,它们的颜色无关紧要)。
当您向下或向上滚动时,文本已经按照您的意愿着色,您将无需执行任何操作。
因此,您将获得所需的行为,同时减少计算开销,因为您不会在每个滚动事件中执行颜色更改任务。

这是我的意思的最小,完整且可重复的示例:

#include <QApplication>
#include <QFile>
#include <QTextEdit>
#include <QDebug>

int main(int argc, char ** argv)
{
    QApplication app(argc, argv);

    QFile data_file("path/to/data/file/some_data.txt");
    if(!data_file.open(QIODevice::ReadOnly | QIODevice::Text))
        return -1;

    // ---------- ---------- ---------- ---------- ----------
    // Set the text color
    QTextEdit view;
    view.setTextColor(Qt::darkGreen);

    // read 100 chars by 100 chars (set the value you want)
    unsigned int MAX_LEN(100);

    // Create the temporary buffer
    char * part = new char[MAX_LEN];
    // Read the file part by part
    qint64 readBytes;
    while((readBytes = data_file.read(part, MAX_LEN)) > 0)
    {
        view.insertPlainText(QString(part).left(static_cast<int>(readBytes)));
    }

    // destroy the temporary buffer
    delete[] part;
    // ---------- ---------- ---------- ---------- ----------

    data_file.close();

    view.show();

    return app.exec();
}

编辑:

如果QPlainTextEditQPlainTextEdit. 在滚动事件中,您可以QPlainTextEdit::textCursor()结合使用QTextCursor::atStart()andQTextCusrsor::atEnd()来检测用户是否已到达显示部分的开头或结尾。例如,如果用户已到达终点,您将获得光标位置,并使用它来设置以下部分而不是当前部分(可能使用重叠部分以使技巧更流畅)。


推荐阅读