此处:Qt multi-thread with GUI我学习了如何创建后台工作程序(Engine
类)。
在那个类中,我有一个 QSerialPort
对象,在主线程中运行(参见 How to setup QSerialPort on a separate thread?)。
我正在使用信号/槽机制来发送/接收数据。但它仅以单向方式工作。 Engine
对象(“工作线程”)发出的信号由 QSerialPort
(“主线程”)接收。反之亦然:QSerialPort
发出的任何信号都不会被 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
引擎.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();
}
行为是一样的:发送了数据,但是从不执行接收槽。
最佳答案
bool MySerial::open(QString port, quint32 baudrate)
{
//<s>disconnect(this, 0, 0, 0);</s> // <--- strikeout
connect(this, &FemtoSerial::readyRead, this, &MySerial::onReadyRead);
// ...
}
来自文档:
Disconnect everything connected to an object's signals
disconnect(myObject, 0, 0, 0);
这意味着来自 myObject
的信号,而不是相反。
该行阻止 Engine
中的插槽执行,因为它刚刚与源信号断开连接。
Engine
可能会在端口关闭时断开连接,以避免在下次打开时出现多个连接。
关于c++ - Qt5多线程: signals work in one-way only,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45553794/