如何让 QTextBrowser 始终在末尾插入文本

How to get QTextBrowser to always insert text at the end

我正在尝试通过使用 QTextBrowser 来制作一个串行终端程序来显示来自串行端口的输入数据。我设置了一个 QTimer 以每 100 毫秒调用一次 paintEvent,并在 QTextBrowser 小部件上显示字符,如果在串行端口上收到任何内容。

我的问题是,每次我点击 QTextBrowser 中间的 say 时,就好像光标移动了,然后在所有后续 ui->tbOutput->insertPlainText(QString(buf)); 上,只有 [=] 的一半11=] 得到更新。

当我点击 QTextBrowser 小部件的底部时,整个 QTextBrowser 再次更新。

这是我的代码,在其他各种文章中,我尝试滚动到底部,并将文本光标移动到末尾,但它没有达到我想要的效果。

void MainWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    static char buf[10240];

    if (terminal->serialport.bytesAvailable() > 0)
    {
        // sizeof(buf)-1 so that there is space for zero termination character
        qint64 numread = terminal->serialport.read(buf,sizeof(buf)-1); 

        if ((numread > 0) && (numread < sizeof(buf)))
        {
            buf[numread] = 0; // set zero termination
            ui->tbOutput->insertPlainText(QString(buf));
            ui->tbOutput->verticalScrollBar()->setValue(
                ui->tbOutput->verticalScrollBar()->maximum());

            ui->tbOutput->textCursor().setPosition(QTextCursor::End);
        }
    }
}

一些事情:

  • QTextBrowser::textCursor returns 一个副本,所以任何修改都不会应用于文档
  • QTextBrowser::setPosition moves the cursor to an absolute position, therefore you are always moving to position 11 (int value to QTextCursor::End). Use QTextBrowser::movePosition 改为
  • 最后,最好在添加文本之前移动光标,这样您就可以确定它会添加到文档的末尾。

这里是修改后的代码:

void MainWindow::paintEvent(QPaintEvent *event)
{
    Q_UNUSED(event);

    static char buf[10240];

    if (terminal->serialport.bytesAvailable() > 0)
    {
        // sizeof(buf)-1 so that there is space for zero termination character
        qint64 numread = terminal->serialport.read(buf,sizeof(buf)-1); 

        if ((numread > 0) && (numread < sizeof(buf)))
        {
            buf[numread] = 0; // set zero termination
            auto textCursor = ui->tbOutput->textCursor();
            textCursor.movePosition(QTextCursor::End);
            ui->tbOutput->setTextCursor(textCursor);
            ui->tbOutput->insertPlainText(QString(buf));
            ui->tbOutput->verticalScrollBar()->setValue(
                ui->tbOutput->verticalScrollBar()->maximum());
        }
    }
}

另一方面,一些额外的注意事项:

  • QIODevice::read(char* data, qint64 maxSize) 将最多读取 maxSize 个字节,因此无需检查读取的字节数是否小于您的缓冲区。
  • 不要在paintEvent里面做,这里不是读取数据的地方,而是显示数据的地方。相反,将计时器与插槽连接并在那里读取数据,并仅在新数据到达时才重新绘制控制台 (ui->tbOutput->update())。