如何让 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()
)。
我正在尝试通过使用 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 toQTextCursor::End
). UseQTextBrowser::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()
)。