В целях разрешения я создал 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).
Это код, который воспроизводит ошибку:
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;
}
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
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();
}
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();
}
}
}
Моя программа довольно сложная (много свойств и классов для совместного использования с интерфейсом), и мне не хотелось бы создавать класс интерфейса только для подключения моих свойств... Есть ли у вас какие-либо предложения по этот вопрос?