【问题标题】:qt-updating ui by threadqt-通过线程更新ui
【发布时间】:2015-01-10 10:51:54
【问题描述】:

您好,我在通过线程更新 ui 时遇到问题。 代码工作正常,但问题是当我想移动我的窗口时,你知道那一刻 ui 线程将停止更新。我的线程将值发送到导致错误的停止线程。 我不知道如何解决这个问题。

这是我的线程代码标题:

#ifndef READERTHREAD_H
#define READERTHREAD_H
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
#include <QThread>

class readerThread : public QThread
{
    Q_OBJECT
public:
    explicit readerThread(QObject *parent = 0);
    void run();
    bool stop = false;
    QByteArray port_input;
    QByteArray payload;
    quint8 starter_symbol = 0;
    quint8 message_length = 0;
    quint8 message_ID = 0;
    readerThread *thread;
signals:
    void updated(QByteArray , quint8);

private:
    QSerialPort *serial;

};

#endif // READERTHREAD_H

我的线程.cpp:

#include "readerthread.h"
#include <QtCore>

readerThread::readerThread(QObject *parent) :
    QThread(parent)
{

    serial = new QSerialPort(this);

    foreach (const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts())
    serial->setPortName(serialPortInfo.portName());

    serial->setBaudRate(QSerialPort::Baud115200);

    serial->setDataBits(QSerialPort::Data8);

    serial->setParity(QSerialPort::NoParity);

    serial->setFlowControl(QSerialPort::NoFlowControl);

    serial->setStopBits(QSerialPort::OneStop);

//    serial->setReadBufferSize(8192);

    serial->open(QIODevice::ReadOnly);

    serial->errorString();

}

void readerThread::run()
{
    while(serial->isOpen())
    {
        port_input.append(serial->readAll());
        if(port_input.count() >= 150)
        {
           starter_symbol = port_input.indexOf(254);
           if((port_input.at(starter_symbol + 3) == 01) && (port_input.at(starter_symbol + 4) == 01))
           {
              message_length = port_input.at(starter_symbol + 1);
              message_ID = port_input.at(starter_symbol + 5);
              payload = port_input.mid(starter_symbol + 6 , message_length);
              port_input.remove(starter_symbol , message_length + 8);
              emit updated(payload , message_ID);
           }
           port_input.remove(0 , starter_symbol);
        }
    }
}

这里是我的 mainwindow.cpp :

   struct mavlink_attitude_t
        {
            /// <summary> Timestamp (milliseconds since system boot) </summary>
              quint32 time_boot_ms;
                /// <summary> Roll angle (rad, -pi..+pi) </summary>
              float roll;
                /// <summary> Pitch angle (rad, -pi..+pi) </summary>
              float pitch;
                /// <summary> Yaw angle (rad, -pi..+pi) </summary>
              float yaw;
                /// <summary> Roll angular speed (rad/s) </summary>
              float rollspeed;
                /// <summary> Pitch angular speed (rad/s) </summary>
              float pitchspeed;
                /// <summary> Yaw angular speed (rad/s) </summary>
              float yawspeed;

        };

    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        thread = new readerThread(this);
        connect(thread , SIGNAL(updated(QByteArray,quint8)) , this , SLOT(onUpdate(QByteArray,quint8)));
        thread->start();

    }

        void MainWindow::onUpdate(QByteArray payload , quint8 ID)
        {
               mavlink_attitude_t data;
               memcpy(&data,payload.data(),sizeof(mavlink_attitude_t));
               ui->timebootms->setText(QString::number(data.time_boot_ms));
               ui->roll->setText(QString::number(data.roll));
               ui->pitch->setText(QString::number(data.pitch));
               ui->yaw->setText(QString::number(data.yaw));
               ui->rollspeed->setText(QString::number(data.rollspeed));
               ui->pitchspeed->setText(QString::number(data.pitchspeed));
               ui->yawspeed->setText(QString::number(data.yawspeed));
        }

【问题讨论】:

  • 您可以尝试强制连接为 Qt::QueuedConnection (这应该已经自动完成)。不确定如果没有事件循环,您的线程信号是否会正常。可以尝试创建一个在本机 QThread(信号槽支持)中运行的线程对象,或者只使用 QtConcurrent
  • 感谢您的宝贵时间。没有事件循环是什么意思?
  • 您的 connect 具有默认的最后一个参数 (Qt::AutoConnection)。这意味着在主线程上调用onUpdate(窗口分配给主线程)。因此,请确认您确定问题的根源是什么。
  • 感谢@Mark R 抽出宝贵时间,是的,我确定问题就是我所说的。我想知道是否有任何方法可以在某种情况下暂停线程并在此之后恢复它?

标签: c++ multithreading qt qtserialport qtwidgets


【解决方案1】:

您可能遇到了我们不久前为 5.5 版本修复的这个问题:

Stopping streaming when window is resizing or moving

如果您愿意,您可以向后移植更改。

更重要的是,当库被设计为具有异步 API 时,自己使用线程是比较奇怪的。那时我写了一个简单的例子,它演示了库的正确异步使用以用于阅读目的。你可以在这里找到它:

Command Line Reader Async Example

【讨论】:

  • 感谢您的时间和回答。我知道你确切地知道我的问题在哪里,但我认为没有线程我无法做到这一点!因为这段代码只是我代码的一小部分。实际上在这里我只想读取串口数据并解析它。我正在从 arduino 设备读取数据,该设备不间断地发送太多不同的数据包,我想用该数据更新至少 20 个小部件,我也有这个 ui 问题!你确定这个例子能解决我的问题吗?
  • 我编译你的例子,输出是: 用法:C:\Qt\Qt5.3.1\Tools\QtCreator\bin\build-SerialportReader-Desktop_Qt_5_3_MSVC2013_64bit-Debug\debug\SerialportReader.exe [波特率] 我错过了什么?
  • @HamedBB:请暂时忘记线程并假设您可能不对。然后,尝试了解这个简单示例的工作原理以及原因,然后尝试将其集成到您的应用程序中。如果由于某种原因无法解决,请尝试从 A-Z 中准确地解释您的用例。否则,将很难提供帮助。
  • @HamedBB:你为什么要删除选择的答案状态?我不问它 -15 的声誉,但更像是图书馆的设计在过去两周没有改变的事实。 o_O
  • @HamedBB:没有任何巨大的延迟。这取决于你在那里放了多少延迟。例如,我们设置了一个常数,但您可以设置任何您喜欢的值,甚至是皮秒。
猜你喜欢
  • 1970-01-01
  • 2015-11-16
  • 1970-01-01
  • 1970-01-01
  • 2023-04-02
  • 2015-12-16
  • 1970-01-01
  • 1970-01-01
  • 2012-11-22
相关资源
最近更新 更多