QML中使用多线程的方法,将Socket服务端作为线程为例子

环境: 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()函数就行了

展示:

 结语:

此文章重在记录,如若对您有帮助,倍感荣幸。

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
QML使用C++多线程显示摄像头可以分为以下几个步骤: 1. 创建一个C++类来处理摄像头捕获和处理的逻辑,例如: ```cpp class Camera : public QObject { Q_OBJECT public: Camera(QObject *parent = nullptr); ~Camera(); public slots: void start(); void stop(); signals: void frameReady(QImage image); private: QThread *m_thread; QCamera *m_camera; QCameraImageCapture *m_imageCapture; bool m_running; void captureFrame(); }; ``` 2. 在QML创建一个Item用于显示摄像头捕获的图像,例如: ```qml Item { id: cameraView width: 640 height: 480 Image { id: cameraImage width: parent.width height: parent.height fillMode: Image.PreserveAspectFit } } ``` 3. 创建一个QML的JavaScript函数,在该函数创建Camera对象,并将其移动到另一个线运行,例如: ```qml function startCamera() { var camera = new Camera(); camera.moveToThread(camera.thread); camera.frameReady.connect(function(image) { cameraImage.source = image; }); camera.start(); } ``` 4. 在Camera类的实现使用QImage处理摄像头捕获的图像,并通过信号frameReady将处理后的图像传递给QML的JavaScript函数。 ```cpp void Camera::captureFrame() { while(m_running) { QVideoFrame frame = m_imageCapture->capture(); if(frame.isValid()) { QImage image = QImage(frame.bits(), frame.width(), frame.height(), frame.bytesPerLine(), QVideoFrame::imageFormatFromPixelFormat(frame.pixelFormat())); emit frameReady(image); } } } ``` 5. 在Camera类的start函数,创建QThread对象并将Camera对象移动到该线运行。 ```cpp void Camera::start() { if(!m_running) { m_running = true; m_thread = new QThread(); connect(m_thread, &QThread::finished, this, &Camera::deleteLater); connect(m_thread, &QThread::started, this, &Camera::captureFrame); moveToThread(m_thread); m_thread->start(); } } ``` 6. 在Camera类的stop函数,停止线程并释放资源。 ```cpp void Camera::stop() { if(m_running) { m_running = false; m_thread->quit(); m_thread->wait(); delete m_thread; m_thread = nullptr; } } ``` 这样,在QML调用startCamera函数即可启动摄像头捕获和处理,并在cameraImage显示处理后的图像。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值