Mur*_*aki 10 c++ qt multithreading qml
出于解决方案的目的,我创建了一个重复我遇到的问题的TestApp.
我将我的软件从Qt 4.8移植到Qt 5.1.
我的第一个程序是多线程的,并且与QML一起工作顺利,只要这些类是线程安全的.但现在我收到这条消息:
QObject::connect: No such slot TestApp::run() in ..\ThreadingTest\main.cpp:21
QQmlEngine: Illegal attempt to connect to TestApp(0x29cfb8) that is in a different thread than the QML engine QQmlEngine(0x2f3e0f8).
Run Code Online (Sandbox Code Playgroud)
这是重现错误的代码:
main.cpp:
#include <QtGui/QGuiApplication>
#include <QQmlContext>
#include <QThread>
#include "qtquick2applicationviewer.h"
#include "testapp.h"
int main(int argc, char *argv[])
{
int out;
QGuiApplication app(argc, argv);
QtQuick2ApplicationViewer viewer;
TestApp * testapp = new TestApp();
QThread * testappThread;
testappThread = new QThread();
QObject::connect(testappThread, SIGNAL(started()), testapp, SLOT(run()));
testapp->moveToThread(testappThread);
testappThread->start();
viewer.rootContext()->setContextProperty("TestApp", testapp);
viewer.setMainQmlFile(QStringLiteral("qml/ThreadingTest/main.qml"));
viewer.showExpanded();
out = app.exec();
testappThread->quit();
testappThread->wait();
delete testapp;
delete testappThread;
return out;
}
Run Code Online (Sandbox Code Playgroud)
testapp.h:
#ifndef TESTAPP_H
#define TESTAPP_H
#include <QObject>
#include <QString>
#include <QTimer>
#include <QReadWriteLock>
#define HELLOWORLD "Hello World !"
extern QReadWriteLock HelloWorldLock;
class TestApp : public QObject
{
Q_OBJECT
Q_PROPERTY(QString HelloWorld READ getHelloWorld WRITE setHelloWorld NOTIFY HelloWorldChanged)
public:
explicit TestApp(QObject *parent = 0);
virtual ~TestApp();
QString getHelloWorld();
void setHelloWorld(QString);
public slots:
void run();
void toggleHelloWorld();
signals:
void HelloWorldChanged();
private:
QString m_HelloWorld;
QTimer * m_Timer;
};
#endif // TESTAPP_H
Run Code Online (Sandbox Code Playgroud)
testapp.cpp:
#include "testapp.h"
QReadWriteLock HelloWorldLock(QReadWriteLock::Recursive);
TestApp::TestApp(QObject *parent) :
QObject(parent)
{
HelloWorldLock.lockForWrite();
m_HelloWorld = HELLOWORLD;
HelloWorldLock.unlock();
m_Timer = new QTimer(this);
connect(m_Timer, SIGNAL(timeout()), this, SLOT(toggleHelloWorld()));
}
TestApp::~TestApp() {
m_Timer->stop();
delete m_Timer;
}
QString TestApp::getHelloWorld() {
HelloWorldLock.lockForRead();
QString out = m_HelloWorld;
HelloWorldLock.unlock();
return out;
}
void TestApp::setHelloWorld(QString text) {
HelloWorldLock.lockForWrite();
m_HelloWorld = text;
HelloWorldLock.unlock();
emit HelloWorldChanged();
}
void TestApp::run() {
m_Timer->start(1000);
}
void TestApp::toggleHelloWorld() {
HelloWorldLock.lockForWrite();
if(m_HelloWorld == "") {
m_HelloWorld = HELLOWORLD;
}
else {
m_HelloWorld = "";
}
HelloWorldLock.unlock();
emit HelloWorldChanged();
}
Run Code Online (Sandbox Code Playgroud)
main.qml:
import QtQuick 2.0
Rectangle {
width: 360
height: 360
Text {
text: TestApp.HelloWorld
anchors.centerIn: parent
}
MouseArea {
anchors.fill: parent
onClicked: {
Qt.quit();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我的程序非常复杂(很多属性和类与界面共享)我不想创建一个接口类只是为了连接我的属性...你有什么建议来处理这个问题吗?
你不需要自己编写应用程序,因为在Qt5中,QML 2引擎已经是大规模多线程的,所以只需启动QQuickView,向上下文公开你需要的C++部分,在其中设置QML文件,然后显示() .这就足够了.不要试图自己修改QML线程,这在QML1中实际上更复杂.