Я пытаюсь сделать программу последовательного терминала с помощью QTextBrowser
для отображения входящих данных с последовательного порта. Я установил QTimer
вызывать paintEvent каждые 100 мс и показывать символы на QTextBrowser
виджет, если что-либо было получено по последовательному порту.
Моя проблема в том, что каждый раз, когда я нажимаю сказать в середине QTextBrowser
, как будто курсор перемещается, а затем на все последующие ui->tbOutput->insertPlainText(QString(buf));
только половина QTextBrowser
обновляется.
Когда я нажимаю на нижней части 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
возвращает копию, поэтому любые изменения не применяются к документуQTextBrowser::setPosition
перемещает курсор в абсолютную позицию, поэтому вы всегда перемещаетесь в позицию 11 (значение int в QTextCursor::End
). использование 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()
) только если поступили новые данные.Других решений пока нет …