0

我希望通过Qt 4.8.6从串口读取一些字符或字符串并用QTextBrowse显示它们并调用以下函数(textBrowser是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);
}

但是,每次我无法在 textBrowser 中正确显示字符或字符串。这些输入字符串总是被切割成更小的字符串,以便在 textBrowser 中以多行显示。例如,字符串“0123456789”可能显示为(多行):

01
2345
6789

如何处理这个问题?非常感谢。

4

1 回答 1

0

发生的情况是,readyRead信号不是在接收到所有内容之后触发,而是在接收到某些内容并准备好读取之后触发。

无法保证在您收到第一封邮件时所有内容都已送达或可读readyRead
这对于几乎任何类型的 IO 来说都是一个常见的“问题”,尤其是在数据大于很少字节的情况下。通常没有自动方式知道何时收到所有数据。

有几种可能的解决方案
所有这些都需要您将数据放在 readSerialPort() 的缓冲区中,而不是直接将其添加到文本浏览器中。也许 SimApplianceQt 中的一个简单的 QByteArray 成员变量已经可以解决您的问题。

其余的取决于确切的解决方案。

  1. 如果您有权访问数据的发送者,则可以在发送实际字符串之前发送将要发送的字节数。这必须始终为相同大小的整数类型(例如,始终为 quint32)。然后,在 readSerialPort() 中,您将首先读取该大小,然后继续在 readSerialPort() 中将字节读取到您的缓冲区,直到所有内容都已收到。然后,你终于可以打印它了。我会推荐那个。它也是在几乎所有出现此问题的情况下使用的。
  2. 如果您有权访问数据的发送者,则可以在字符串末尾发送某种“结束序列”。在您的 readSerialPort() 中,您将继续将字节读入缓冲区,直到您收到该结束序列。收到结束序列后,您可以打印之前的所有内容。请注意,结束序列本身可能会被中断,因此您也必须注意这一点。
  3. 如果您无权访问发件人,我能想到的最好的办法是使用计时器。每次调用 readSerialPort() 时,您都将所有内容放入缓冲区并重新启动该计时器。当计时器用完时,这意味着有一段时间没有发送新数据,您可能可以打印到目前为止的数据。这是...有风险的,如果有任何其他方式,我不会推荐它。
于 2017-12-20T09:43:32.293 回答