环境: VS2017 + QT4.12.2
方法:
这边以在QML中将纯C++写的Socket当作线程为例子
整体框架展示如下图:
First:
新建一个c++Class取名为"myobject"
Second:myobject.h代码示例
#ifndef MYOBJECT_H
#define MYOBJECT_H
#include <QObject>
#include <QDebug>
#include <WinSock2.h>
class Myobject: public QObject
{
Q_OBJECT
public:
explicit Myobject(QObject *parent = nullptr);
Q_INVOKABLE void fun();
Q_INVOKABLE void fun1();
Q_INVOKABLE QString getData();
Q_INVOKABLE void setData(char *data);
WSADATA wsadata;
signals:
void cppSig(QVariant i, QVariant s);
public slots:
private:
char cBuffer[1024];
};
#endif // MYOBJECT_H
Third:myobject.cpp代码示例
#include "myobject.h"
#include <QThread>
#include <QDebug>
#include <iostream>
#include <string>
#include <tchar.h>
#include <Windows.h>
#include <winsock.h>
#include <cstring>
Myobject::Myobject(QObject *parent) : QObject(parent)
{
}
char pop[10]= {'a','b','c','d'};
int nRs = 1;
void Myobject::fun(){
emit cppSig(0, "Linwz");
qDebug()<<"i am fun";
QThread::create([&]() {
qDebug()<<"i am a thread and i am fun 1" ;
int recvLenths = 0;
int nLenPro = 0;
char cDatas[1024];
std::string sLenths = "";
char cLenths[100];
int nCount = 0;
char cBuff[10];
//char *sBuffer = {};
// 204 5
memset(cLenths,0,sizeof(cLenths));
//std::string strs = "i am lwz";
memset(cBuffer,0,sizeof(cBuffer));
if(WSAStartup(MAKEWORD(2, 0),&wsadata) !=0){
qDebug()<<"Socket Initial Failure";
}
int nServiceSock = socket(AF_INET, SOCK_STREAM, 0);
qDebug()<<nServiceSock;
struct sockaddr_in servaddr;
memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htons(34257);
servaddr.sin_addr.s_addr = inet_addr("192.168.55.208");
int nBind = bind(nServiceSock, (struct sockaddr*)&servaddr, sizeof(servaddr));
if(nBind < 0){
qDebug()<<nBind;
perror("bind");
exit(1);
}
if(listen(nServiceSock, 5) < 0){
perror("listen");
exit(1);
}
qDebug()<<"wait Client link.....";
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
int nClient = accept(nServiceSock, (struct sockaddr*)&remoteAddr, &nAddrlen);
if(nClient < 0){
qDebug()<<"[nClient] error";
exit(1);
}
while(nRs){
qDebug()<<"等待接收数据~~~~~~~";
qDebug()<<"nClient:"<<nClient;
int nChangdu = recv(nClient, cLenths, sizeof(cLenths), 0);
// for(int i=0; i<sizeof(cLenths); i++){
// sLenths += cLenths[i];
// }
recvLenths = atoi(cLenths);
qDebug()<<recvLenths<<"*************";
if(recvLenths != 0){
int nLen = recv(nClient, cBuffer, recvLenths, 0);
if(nLen < 0){
perror("recv:");
if(errno == EAGAIN){
break;
}
else{
return;
}
}
else if(nLen == recvLenths){
qDebug()<<"entry else";
qDebug()<<nLen<<"!!!!!!!!";
//emit sendDxfData(cBuffer);
setData(cBuffer);
qDebug()<<"emit shifou success";
}
}
}
})->start();
}
void Myobject::fun1()
{
qDebug() << "fun1";
QThread::create([&]() {
while (1) {
qDebug()<<"test program";
}
})->start();
}
QString Myobject::getData(){
QString qstr;
qstr = QString(cBuffer);
return qstr;
}
Fourth:main.cpp代码示例
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include <QQmlContext>
#include "myobject.h"
int main(int argc, char *argv[])
{
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
QGuiApplication app(argc, argv);
// Myobject *myobj = new Myobject();
qmlRegisterType<Myobject>("Myobject",1, 0, "Myobj");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
// auto list = engine.rootObjects();
// auto window = list.first();
// qDebug()<<window->objectName();
// QObject::connect(myobj,SIGNAL(cppSig(QVariant, QVariant)), window,
// SLOT(qmlSlot(Qvariant, QVariant)));
// myobj->fun(); // 一运行就启动fun()线程(可屏蔽).在main.qml中通过按钮开启线程
return app.exec();
}
qmlRegisterType<Myobject>("Myobject",1, 0, "Myobj");此行代码将Myobject以Myobj为名字注册,然后在main.qml中可以使用。记得要在main.qml中加上 import Myobject 1.0 和 注册一个新ID。这样子就可以调用我们的函数了如:myobj.fun()
Fiveth:main.qml代码示例
import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Controls 2.0
import Myobject 1.0
Window {
visible: true
width: 640
height: 480
title: qsTr("Hello World")
/*注册一个新ID*/
Myobj{
id:myobj
}
function qmlSlot(i, s){
console.log("qml",i,s)
}
Row{
anchors.centerIn: parent
spacing: 20
Button{
text: "开启服务器"
onClicked: {
myobj.fun()
}
}
Button{
text: "获取DXF数据"
onClicked: {
myobj.getData()
console.log(myobj.getData())
}
}
}
Label{
width: 200
height:200
background: Rectangle{
color:"red"
radius:20
}
text: "测试Label"
}
}
总结:
1)fun()和fun1()相当于两个线程在myobject.cpp的start中开始线程,在main.qml中启动线程代码,fun()里面放的是socket服务端代码,fun1()里面放的是简单的打印条例。
2)getData()函数是为了将fun()接收到的数据传到main.qml。相当于实现数据与main.qml的交互。
3)如若只是使用QML的多线程功能,请忽略fun()函数,看fun1()函数就行了
展示:
结语:
此文章重在记录,如若对您有帮助,倍感荣幸。