В следующем коде, если сигнал errorHappened
излучается из основного потока, он работает без проблем. Однако, если он излучается из потока QThread
, происходит сбой со следующей ошибкой:
QObject::connect: Cannot queue arguments of type 'ErrorCode'
(Make sure 'ErrorCode' is registered using qRegisterMetaType().)
Есть ли способ, что сигнал может быть успешно излучен из потока QThread
? Если да, то как?
Полный код в этом списке
MyClass.h
#import <QThread>
#import <atomic>
class MyClass : public QThread
{
Q_OBJECT
public:
explicit MyClass(QObject *parent = Q_NULLPTR);
virtual ~MyClass() override;
enum ErrorCode {
ErrorA,
ErrorB,
ErrorC
};
Q_ENUM(ErrorCode)
signals:
void errorHappened(ErrorCode errorCode);
public slots:
void mainThreadError();
void otherThreadError();
private:
std::atomic<bool> m_running;
std::atomic<bool> m_signalStop;
std::atomic<bool> m_signalError;
void run() override;
void stop();
};
MyClass . cpp
#include "MyClass.h"
MyClass::MyClass(QObject *parent)
: QThread(parent)
{
start();
}
MyClass::~MyClass()
{
stop();
}
void MyClass::mainThreadError()
{
emit errorHappened(ErrorCode::ErrorA);
}
void MyClass::otherThreadError()
{
m_signalError = true;
}
void MyClass::run()
{
m_running = true;
while (!m_signalStop) {
if (m_signalError) {
emit errorHappened(ErrorCode::ErrorA);
m_signalError = false;
}
msleep(1);
}
m_running = false;
m_signalStop = false;
}
void MyClass::stop()
{
if (m_running) {
m_signalStop = true;
wait();
}
}
main. cpp
#include <QGuiApplication>
#include <QQuickView>
#include "MyClass.h"
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView *view = new QQuickView();
qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
view->setSource((QUrl(QStringLiteral("qrc:/main.qml"))));
view->create();
view->show();
return app.exec();
}
main.qml
import QtQuick 2.12
import QtQuick.Controls 2.5
import MyClass 1.0
Rectangle {
id: root
width: 800
height: 600
focus: true
MyClass {
id: tester
onErrorHappened: {
var s
switch (errorCode) {
case MyClass.ErrorA:
s = "Error A happened"
break
}
console.log(s)
}
}
Row {
spacing: 30
Button {
id: mainThreadButton
enabled: !tester.testRunning
text: "Test on main thread"
onClicked: tester.mainThreadError()
}
Button {
id: otherThreadButton
enabled: !tester.testRunning
text: "Test on other thread"
onClicked: tester.otherThreadError()
}
}
}