此处:Qt multi-thread with GUI我已经学会了如何创建后台工作者(Engine
类)。
在该课程中,我有一个QSerialPort
对象,在主线程中运行(参见How to setup QSerialPort on a separate thread?)。
我使用信号/插槽机制发送/接收数据。但它只在单向工作。 Engine
对象("工作线程")发出的信号由QSerialPort
("主线程")接收。反之亦然:QSerialPort
未收到Engine
发出的任何信号。
engine.h
#ifndef ENGINE_H
#define ENGINE_H
#include <QObject>
#include <QTimer>
#include "myserial.h"
class Engine : public QObject
{
Q_OBJECT
public:
explicit Engine(QObject *parent = 0);
private:
QTimer m_timer;
MySerial m_serial;
signals:
void serialSendMessage(QByteArray data);
private slots:
void lineReceived(QByteArray line);
void foo();
public slots:
void run();
void open(QString port, quint32 baudrate);
void close();
};
#endif // ENGINE_H
engine.c
#include "engine.h"
#include <QDebug>
Engine::Engine(QObject *parent) : QObject(parent)
{
connect(&m_timer, &QTimer::timeout, this, &Engine::foo);
m_timer.setInterval(200);
}
// THIS IS NEVER EXECUTED!
void Engine::lineReceived(QByteArray line)
{
qDebug() << line;
}
// THIS IS RECEIVED BY QSERIALPORT
void Engine::foo()
{
emit serialSendMessage("Hello World!");
}
void Engine::run()
{
// THIS DOESN'T WORK!
connect(&m_serial, &MySerial::lineReceived, this, &Engine::lineReceived);
// THIS WORK!
connect(this, &Engine::serialSendMessage, &m_serial, &MySerial::sendMessage);
}
void Engine::open(QString port, quint32 baudrate)
{
m_serial.open(port, baudrate);
QTimer::singleShot(0, &m_timer, static_cast<void (QTimer::*)(void)>(&QTimer::start));
}
void Engine::close()
{
m_serial.close();
}
MySerial.h
#ifndef MYSERIAL_H
#define MYSERIAL_H
#include <QObject>
#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>
class MySerial : public QSerialPort {
Q_OBJECT
public:
explicit MySerial(QObject *parent = 0);
bool open(QString port, quint32 baudrate);
using QSerialPort::open;
QByteArray sendMessage(QByteArray data, bool nmea);
signals:
void lineReceived(QByteArray line);
private slots:
void onReadyRead();
};
#endif // MYSERIAL_H
MySerial.c
#include "myserial.h"
#include <QDebug>
MySerial::MySerial(QObject *parent) : QSerialPort(parent) {
}
bool MySerial::open(QString port, quint32 baudrate)
{
disconnect(this, 0, 0, 0);
connect(this, &FemtoSerial::readyRead, this, &MySerial::onReadyRead);
setPortName(port);
if (!open(QIODevice::ReadWrite)) return false;
setDataBits(QSerialPort::Data8);
setParity(QSerialPort::NoParity);
setStopBits(QSerialPort::OneStop);
setBaudRate(baudrate);
setFlowControl(QSerialPort::NoFlowControl);
return true;
}
void MySerial::onReadyRead() {
static QList<QByteArray> lines;
static QByteArray buffer;
buffer += readAll();
int index = buffer.indexOf("\r");
while (index != -1) {
lines.append(buffer.left(index + 1));
buffer = buffer.mid(index + 1);
index = buffer.indexOf("\r");
}
// THIS SIGNAL IS EMITTED!
while (!lines.isEmpty()) emit lineReceived(lines.takeFirst());
}
QByteArray MySerial::sendMessage(QByteArray data) {
write(data);
return data;
}
尝试添加QEventLoop
:
void Engine::run()
{
QEventLoop loop;
connect(&m_serial, &MySerial::lineReceived, this, &Engine::lineReceived);
connect(this, &Engine::serialSendMessage, &m_serial, &MySerial::sendMessage);
loop.exec();
}
行为相同:发送数据,但从不执行接收槽。
答案 0 :(得分:1)
bool MySerial::open(QString port, quint32 baudrate)
{
//<s>disconnect(this, 0, 0, 0);</s> // <--- strikeout
connect(this, &FemtoSerial::readyRead, this, &MySerial::onReadyRead);
// ...
}
来自文档:
断开连接到对象信号的所有内容
disconnect(myObject,0,0,0);
它意味着来自myObject
的信号,而不是相反。
该行阻止执行Engine
中的插槽,因为它刚刚与源信号断开连接。
Engine
可能会断开连接,以避免下次打开时出现多个连接。