Qt和Qml互動,及多執行緒
阿新 • • 發佈:2019-02-17
註冊一個物件給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;
}
}