QML中用C++多线程读取网页内容

在一开始我想在网页上爬取一些内容所以我想到了C++中的 QNetworkAccessManager 类
然后很自然的写了

    QNetworkRequest request;
    request.setUrl(QUrl(m_url) );
    QNetworkReply * qreply= manager->get(request );

但是这并不可以控制超时时间,我一直以为QNetworkAccessManager这么大一个类一定有设置超时时间的地方,然后也去网上查找发现并没有. 于是发现别人的一个方法 QReplyTimeout :

#ifndef REPLYTIMEOUT_H
#define REPLYTIMEOUT_H

/**
QReplyTimeout 控制超时时间

**/

#include <QObject>
#include <QTimer>
#include <QNetworkReply>

class QReplyTimeout : public QObject {

    Q_OBJECT

public:
    QReplyTimeout(QNetworkReply *reply, const int timeout) : QObject(reply) {
        Q_ASSERT(reply);
        if (reply && reply->isRunning()) {  // 启动单次定时器
            QTimer::singleShot(timeout, this, SLOT(onTimeout()));
        }
    }

signals:
    void timeout();  // 超时信号 - 供进一步处理

private slots:
    void onTimeout() {  // 处理超时
        QNetworkReply *reply = static_cast<QNetworkReply*>(parent());
        if (reply->isRunning()) {
            emit timeout();
            reply->abort();
            reply->deleteLater();
        }
    }
};

#endif // REPLYTIMEOUT_H

这个类一看内容就大概知道怎么使用了 于是我将代码改成如下:

    QNetworkAccessManager * manager = new QNetworkAccessManager();
    QNetworkRequest request;
    request.setUrl(QUrl(m_url) );
    QNetworkReply * qreply= manager->get(request );

    QReplyTimeout *pTimeout = new QReplyTimeout(qreply, m_outTime);

    //下载超时
    connect(pTimeout, &QReplyTimeout::timeout, [=]() {
        qDebug() << "Timeout";
        emit responseFaild();
    });

    connect(manager,&QNetworkAccessManager::finished,[=](){
        QString str = qreply->readAll();
            XXX
            qreply->abort();
            qreply->deleteLater();
            emit responseSuccessful(Space2nbsp(rx.capturedTexts()[1]));
        }
    });

这样在电脑上测试没有任何问题,但是在手机android上,如果触碰任何的东西都会导致闪退我猜测是没有多线程的原因.
于是我将 这一整段代码 全都移到了 run中 然后 start 发现并不能 读取内容,因为如果没有让线程消息循环的话,没有时间读取网页,所以在末尾加上 this->exec();

void request::run()
{

    QNetworkAccessManager * manager = new QNetworkAccessManager();
    QNetworkRequest request;
    request.setUrl(QUrl(m_url) );
    QNetworkReply * qreply= manager->get(request );

    QReplyTimeout *pTimeout = new QReplyTimeout(qreply, m_outTime);

    //下载超时
    connect(pTimeout, &QReplyTimeout::timeout, [=]() {
        qDebug() << "Timeout";
        emit responseFaild();
        this->quit();
    });

    //多线程下载数据 成功
    connect(manager,&QNetworkAccessManager::finished,[=](){
        QString str = qreply->readAll();
            XXX
            emit responseSuccessful(Space2nbsp(rx.capturedTexts()[1]));
            this->quit();
        }
    });


    this->exec();
}

在main中 首先要让C++文件可以 被QML发现

#include "Request.h"
int main(int argc, char *argv[])
{
    QGuiApplication app(argc, argv);
    qmlRegisterType<Request>("REQUEST", 1, 0, "Request");// QML导入的时候就是import REQUEST 1.0
}

在QML 中 创建 这个C++对象

    Request{
        id: r_netrequest
        onResponseSuccessful:{
            成功
        }
        onResponseFaild:{
            超时失败等
        }
    }
    启动线程 : r_netrequest.start()
    关闭线程 : r_netrequest.quit()
    我习惯性的加上了     
    //删除界面时 关闭线程
    Component.onDestruction: {
        r_netrequest.quit()
        r_netrequest.wait()
    }
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中显示处理后的图像。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值