QTextBrowser display issue in Qt 4.8.6 - always displayed wrongly

120 Views Asked by At

I hope to read some characters or strings and display them with QTextBrowse from serial port by Qt 4.8.6 and called the following functions( textBrowser is a object of QTextBrowser):

connect(com, SIGNAL(readyRead()), this, SLOT(readSerialPort()));
connect(textBrowser, SIGNAL(textChanged()), SimApplianceQtClass, SLOT(on_textBrowser_textChanged()));

void SimApplianceQt::on_textBrower_textChanged()
{
    ui.textBrowser->moveCursor(QTextCursor::End); 
}

void SimApplianceQt::readSerialPort()
{
    QByteArray temp = com->readAll();
    ui.textBrowser->insertPlainText(temp);
}

However, every time I cannot display characters or strings in the textBrowser rightly. Those input strings are always cut into smaller strings to be displayed in multiple lines in the textBrowser. For example, a string "0123456789" may be displayed as (in multiple lines):

01
2345
6789

How to deal with this issue? Many thanks.

1

There are 1 best solutions below

0
On

What happens is that the readyRead signal is fired not after everything has been received, but after something has been received and is ready to read.

There is no guarantee that everything will have arrived or is readable by the time you receive the first readyRead.
This is a common "problem" for almost any kind of IO, especially if the data is larger than very few bytes. There is usually no automatic way to know when all the data has been received.

There are a few possible solutions:
All of them will require you to put the data in a buffer in readSerialPort() instead of adding it directly to the text browser. Maybe a simple QByteArray member variable in SimApplianceQt would already do the trick in your case.

The rest depends on the exact solution.

  1. If you have access to the sender of the data, you could send the number of bytes that will be sent before sending the actual string. This must always be in an integer type of the same size (for example, always a quint32). Then, in readSerialPort(), you would first read that size, and then continue to read bytes to your buffer in readSerialPort() until everything has been received. And then, you could finally print it. I'd recommend that one. It is also what is used in almost all cases where this problem arises.
  2. If you have access to the sender of the data, you could send some kind of "ending sequence" at the end of the string. In your readSerialPort(), you would then continue to read bytes into your buffer until you receive that ending sequence. Once the ending sequence has been received, you can print everything that came in prior to it. Note that the ending sequence itself could be interrupted, so you'd have to take care of that, too.
  3. If you do not have access to the sender, the best idea I could come up with would be to work with a timer. You put everything into a buffer and re-start that timer each time you readSerialPort() is called. When the timer runs out, that means no new data has been sent for a while and you can probably print what you have so far. This is... risky and I wouldn't recommend it if there is any other way.