**方法:工作对象继承QObject,包含 QThread 指针,创建Object 、创建QThread,然后object moveToThread() **
代码:
QT += core
QT += quick
QT += serialport
CONFIG += c++11
DEFINES += QT_DEPRECATED_WARNINGS
SOURCES += \
main.cpp \
serialinterface.cpp
RESOURCES += qml.qrc
# Additional import path used to resolve QML modules in Qt Creator's code model
QML_IMPORT_PATH =
# Additional import path used to resolve QML modules just for Qt Quick Designer
QML_DESIGNER_IMPORT_PATH =
# Default rules for deployment.
qnx: target.path = /tmp/$${TARGET}/bin
else: unix:!android: target.path = /opt/$${TARGET}/bin
!isEmpty(target.path): INSTALLS += target
HEADERS += \
serialinterface.h
#ifndef SERIALINTERFACE_H
#define SERIALINTERFACE_H
#include
#include
#include
#include
// We use QSerialPort::SerialPortError in a signal so we must declare it as a meta type
Q_DECLARE_METATYPE(QSerialPort::SerialPortError)
Q_DECLARE_LOGGING_CATEGORY(SerialLinkLog)
class SerialInterface : public QObject
{
Q_OBJECT
public:
explicit SerialInterface(QObject *parent = nullptr);
signals:
/*! 线程安全
* \brief 数据转发
* \param link
* \param data
*/
void bytesReceived(SerialInterface* link, QByteArray data);
public slots:
void linkError(QSerialPort::SerialPortError error);
/*! 发送数据
* 1 调用线程执行(主线程)
* 2 槽函数触发,线程安全, Qt::QueuedConnection
*/
Q_INVOKABLE void writeData(QVariant data);
private slots:
/*!
* \brief 接收数据
*
* Qt::DirectConnection
* 槽函数在次线程中执行
*
* Qt::QueuedConnection
* 槽函数在所属对象SerialInterface线程中执行
*/
void _readBytes();
private:
QSerialPort *m_port;
QThread *m_serialThread;
};
#endif // SERIALINTERFACE_H
#include "serialinterface.h"
#include
#include
#include
Q_LOGGING_CATEGORY(SerialLinkLog, "SerialLinkLog")
SerialInterface::SerialInterface(QObject *parent) : QObject(parent)
{
qCDebug(SerialLinkLog)<(&QSerialPort::error),
this, &SerialInterface::linkError, Qt::QueuedConnection);
QObject::connect(m_port, &QIODevice::readyRead, this, &SerialInterface::_readBytes, Qt::QueuedConnection);
// Try to open the port three times
for (int openRetries = 0; openRetries < 3; openRetries++) {
if (!m_port->open(QIODevice::ReadWrite)) {
qCDebug(SerialLinkLog) << "Port open failed, retrying";
// Wait 250 ms while continuing to run the event loop
for (unsigned i = 0; i < 50; i++) {
QThread::msleep(5);
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
}
qApp->processEvents(QEventLoop::ExcludeUserInputEvents);
} else {
break;
}
}
if (!m_port->isOpen() ) {
qCDebug(SerialLinkLog)<< "open failed" << m_port->errorString() << m_port->error();
m_port->close();
delete m_port;
m_port = NULL;
}
m_port->setDataTerminalReady(true);
qCDebug(SerialLinkLog) << "Configuring port";
m_port->setBaudRate (QSerialPort::Baud9600);
m_port->setDataBits (QSerialPort::Data8);
m_port->setFlowControl (QSerialPort::SoftwareControl);
m_port->setStopBits (QSerialPort::OneStop);
m_port->setParity (QSerialPort::NoParity);
//--moveToThread
m_port->moveToThread(m_serialThread);
this->moveToThread(m_serialThread);
m_serialThread->start();
}
void SerialInterface::writeData(QVariant data)
{
if (m_port && m_port->isOpen()) {
m_port->write(data.toByteArray());
qCDebug(SerialLinkLog)<isOpen()) {
qint64 byteCount = m_port->bytesAvailable();
if (byteCount) {
QByteArray buffer;
buffer.resize(byteCount);
m_port->read(buffer.data(), buffer.size());
qCDebug(SerialLinkLog)<
#include
#include
#include
#include
#include "serialinterface.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
qDebug()<("com.ui", 1, 0,"SerialInterface",QStringLiteral("Access to object"));
SerialInterface *serial = new SerialInterface();
engine.rootContext()->setContextProperty("serial", serial);
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
if (engine.rootObjects().isEmpty())
return -1;
//设置qml文件后执行
QObject* rootQmlObject = engine.rootObjects().at(0);
QObject::connect(rootQmlObject,SIGNAL(sendBtnClicked(QVariant)),serial,SLOT(writeData(QVariant)));
return app.exec();
}
import QtQuick 2.9
import QtQuick.Window 2.2
import QtQuick.Controls 2.4
import com.ui 1.0
Window {
id:main
visible: true
width: 640
height: 480
title: qsTr("object moveTo thread")
signal sendBtnClicked(var text)
Button{
id:sendBtn
anchors{
top:parent.top
topMargin: 40
}
text:qsTr("Send")
onClicked: {
//serial.writeData(edit.text)
sendBtnClicked(edit.text)
edit.clear()
}
}
Rectangle{
width: 200
height: 40
anchors{
left:sendBtn.right
leftMargin:10
verticalCenter:sendBtn.verticalCenter
}
color: "transparent"
border.color: "#841775"
border.width: 2
TextEdit{
id:edit
anchors{
fill:parent
}
horizontalAlignment: TextInput.AlignLeft
clip:true
wrapMode: TextEdit.WordWrap
}
}
}
在次线程中执行
主线程中执行
函数调用方式,调用发送函数 : 发送函数在调用者线程中执行
次线程中执行
信号槽方式,触发发送函数 : 发送函数在 次线程中执行
使用虚拟串口 生成 /dev/pts/18 /dev/pts/19 一对串口
/dev/pts/18 用于程序 , 发送 666666666666
/dev/pts/19 用于串口助手,发送 99999999
QML debugging is enabled. Only use this in a safe environment.
int main(int, char**) 0x7f8baae0a780
SerialLinkLog: SerialInterface::SerialInterface(QObject*) 0x7f8baae0a780
SerialLinkLog: Configuring port
SerialLinkLog: void SerialInterface::_readBytes() 0x7f8b8cb00700
SerialLinkLog: "99999999"
SerialLinkLog: void SerialInterface::writeData(QVariant) 0x7f8b8cb00700
SerialLinkLog: void SerialInterface::writeData(QVariant) QVariant(QString, "666666666666")
QObject::connect(rootQmlObject,SIGNAL(sendBtnClicked(QVariant)),serial,SLOT(writeData(QVariant)),Qt::DirectConnection);
** 运行输出 **
使用虚拟串口 生成 /dev/pts/18 /dev/pts/19 一对串口
/dev/pts/18 用于程序 , 发送 fffffff
/dev/pts/19 用于串口助手,发送 ppppppp
QML debugging is enabled. Only use this in a safe environment.
int main(int, char**) 0x7fb575567780
SerialLinkLog: SerialInterface::SerialInterface(QObject*) 0x7fb575567780
SerialLinkLog: Configuring port
SerialLinkLog: void SerialInterface::_readBytes() 0x7fb54f3fe700
SerialLinkLog: "ppppppp"
SerialLinkLog: void SerialInterface::writeData(QVariant) 0x7fb575567780
SerialLinkLog: void SerialInterface::writeData(QVariant) QVariant(QString, "fffffff")