1. 程式人生 > >Qt和Qml互動,及多執行緒

Qt和Qml互動,及多執行緒

註冊一個物件給qml,實現程式碼:
Gamesub.h

#pragma once
#include <QObject>
#include<QVariant>
#include<QQmlApplicationEngine>
#include <QquickItem>
class Gamesub :public QObject
{
    Q_OBJECT
public:
    Gamesub(QObject* parent=NULL);
    ~Gamesub();
    QQmlApplicationEngine*  m_mainroot;
    QQuickItem
* m_page; Q_INVOKABLE void setpage(QQuickItem* page); void setroot(QQmlApplicationEngine* mainroot); Q_INVOKABLE void init(); Q_INVOKABLE void msg(QVariant var); Q_INVOKABLE QVariant getobj(); };

Gamesub.cpp

#include "Gamesub.h"


Gamesub::Gamesub(QObject* parent):QObject(parent)
{
}


Gamesub::~Gamesub()
{
}

Q_INVOKABLE void
Gamesub::setpage(QQuickItem* page) { m_page = page; OutputDebugStringA(m_page->objectName().toStdString().c_str()); } int cout = 0; DWORD thtest(LPVOID lp) { QQuickItem* m_page = (QQuickItem*)lp; QVariant item; //BlockingQueuedConnection 多執行緒 中使用,否則會出錯 bool ret2 = QMetaObject::invokeMethod(m_page, "getitem"
, Qt::ConnectionType::BlockingQueuedConnection, Q_RETURN_ARG(QVariant, item), Q_ARG(QVariant, cout)); if (ret2 == false) { AfxMessageBox("eRROR"); } QObject* obj; obj = item.value<QObject*>(); // 可用item.typeName()獲取返回值型別,然後,使用item.value<型別>() 進行轉換 int var =0; while (true) { var=var+1; if (obj!=NULL && IsBadWritePtr(obj,4)==false) { QMetaObject::invokeMethod(obj, "test", Qt::ConnectionType::QueuedConnection, Q_ARG(QVariant, QString::number(var))); //此處也可修改為 Qt::ConnectionType::BlockingQueuedConnection } Sleep(1000); } return 0; } Q_INVOKABLE void Gamesub::init() { for (int i=0;i<5;i++) { QVariant s; s = i; QMetaObject::invokeMethod(m_page, "addmodel", Q_ARG(QVariant, s.toString())); } QVariant ret; QMetaObject::invokeMethod(m_page, "getlen", Q_RETURN_ARG(QVariant, ret)); //AfxMessageBox(ret.typeName()); AfxMessageBox(ret.toString().toStdString().c_str()); QVariant item; bool ret2 = QMetaObject::invokeMethod(m_page, "getitem", Q_RETURN_ARG(QVariant, item), Q_ARG(QVariant, 0)); if (ret2 == false) { AfxMessageBox("eRROR"); } QObject* obj; obj = item.value<QObject*>(); AfxMessageBox(obj->objectName().toStdString().c_str()); for (int i = 0; i < ret.toInt(); i++) { AfxBeginThread(AFX_THREADPROC(thtest), m_page); Sleep(100); cout++; } } void Gamesub::setroot(QQmlApplicationEngine * mainroot) { m_mainroot = mainroot; } Q_INVOKABLE void Gamesub::msg(QVariant var) { AfxMessageBox(var.toString().toStdString().c_str()); } Q_INVOKABLE QVariant Gamesub::getobj() { if (m_mainroot !=NULL) { QObject *tmp = m_mainroot->findChild<QObject *>("mmodel"); if (tmp!=NULL) { OutputDebugStringA("OK object"); } else { OutputDebugStringA("Null object"); } } return 0; }

main.cpp:

// 首先註冊一下類
    qmlRegisterType<Gamesub>(
        "game",      
        1,                   
        0,                       
        "game");         
    QApplication* app = (QApplication *)QApplication::instance();

    OutputDebugStringA("local file");

    QQmlApplicationEngine engine(app);

    Gamesub*  tmp = new Gamesub();
    tmp->m_mainroot = &engine;
    engine.rootContext()->setContextProperty("game", (QObject*)tmp);
    engine.load(QUrl::fromLocalFile(QStringLiteral("main.qml")));

點選執行,C++程式碼動態新增model,並且在多執行緒中,重新整理UI
Qml檔案:
main.qml

import QtQuick 2.6
import QtQuick.Window 2.2
import Material 0.1  as  Material
import Material.ListItems 0.1 as ListItems
import Material.Extras 0.1     as Ex


Material.ApplicationWindow{
    property Item tmp: null
    visible:  true
        title: "主視窗"
        property var mytabs:  ["主要"]
        theme{
            primaryColor: Material.Palette.colors["blue"]["500"]
            primaryDarkColor: Material.Palette.colors["blue"]["700"]
            accentColor: Material.Palette.colors["teal"]["500"]
            tabHighlightColor: "white"
        }

        initialPage: Material.Page{
            id:mainpage
            title: "主視窗"
            tabs: mytabs

            onSelectedTabChanged: {
                if(selectedTab==1)
                {
                     mainrun.visible=false
                    loader.source=Qt.resolvedUrl("run2.qml")
                    loader.visible=true
                }else{
                        mainrun.visible=true
                    loader.visible=false
                }
            }
            Loader{
                anchors.fill: parent
                visible: false
                id:loader
               // source: Qt.resolvedUrl("run2.qml")
            }

                Material.Button{
                    id:mainrun
                    visible: true
                    text: "執行"
                    elevation: 1
                    onClicked: {

                        mytabs[1]="進行中"
                        mainpage.tabs  =mytabs
                        mainpage.selectedTab=1
                        text="runing"
                    }

                }
        }

        DropArea{
            anchors.fill: parent
            onDropped: {
                for(var i=0;i<drop.urls.length;i++)
                {
                    title=title+drop.text +","
                }


            }
        }
}

run2.qml:

import QtQuick 2.6
import QtQuick.Window 2.2
import Material 0.1  as  Material
import Material.ListItems 0.1 as ListItems
import Material.Extras 0.1     as Ex


Material.View{

id:page
objectName: "mmodel"
 Component.onDestruction: {
        console.log("onDestruction")
 }



        Flow{
            spacing: 5
            anchors.fill: parent
            Repeater{
                id:rey
                model:mmodel
                delegate: componet

            }
            Component.onCompleted: {


                   game.setpage(page);
                   game.init();
            }
        }


        ListModel{
            id:mmodel
            ListElement{txt:"test"}
            ListElement{txt:"test2"}
            ListElement{txt:"test3"}
        }

        Component{
            id:componet
            Material.View{
                id:m_view
                objectName: "index"
                elevation: 3
                width: 120
                height: 300
                anchors.margins: 5
                Column{
                    width: parent.width
                    Material.Button{
                        id:btn
                        elevation: 1
                        width: parent.width
                        text:txt;
                    }
                    Repeater{
                            model: mmodel2
                            delegate: ListItems.Standard{
                                valueText: index
                                itemLabel.font.pixelSize: 14
                                elevation: 1
                                id:labels
                                text: shows

                            }


                }
                }
                ListModel{
                    id:mmodel2
                    ListElement{shows:"test"}
                }
                function  test(txt)
                {
                    if(mmodel2.count>5)
                    {
                        mmodel2.clear()
                        mmodel2.sync()
                    }
                       mmodel2.append({shows:txt})
                }
            }
        }

        function  getitem(index)
        {


            var i= rey.itemAt(index)
            console.log("index:"+index+":"+i)
            return i;
        }

        function  addmodel(argtxt)
        {
            mmodel.append({txt:argtxt})
        }
        function getlen()
        {
            return mmodel.count;
        }

}