QThread如何从自己的线程发送一个信号,并将enum作为QML中使用的参数?
在下面的代码中,如果从主线程发出信号QThread如何从自己的线程发送一个信号,并将enum作为QML中使用的参数?,qt,enums,qml,signals-slots,qthread,Qt,Enums,Qml,Signals Slots,Qthread,在下面的代码中,如果从主线程发出信号errorOccessed,则它可以正常工作。但是,如果它是从QThread线程发出的,则会失败,并出现以下错误: QObject::connect: Cannot queue arguments of type 'ErrorCode' (Make sure 'ErrorCode' is registered using qRegisterMetaType().) 是否有一种方法可以成功地从QThread线程发出信号?如果是,怎么做 MyClass.h #
errorOccessed
,则它可以正常工作。但是,如果它是从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();
};
main.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();
}
}
#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();
}
#include <QGuiApplication>
#include <QQuickView>
#include "MyClass.h"
static void registerTypes(){
qRegisterMetaType<MyClass::ErrorCode>("ErrorCode");
qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
}
Q_COREAPP_STARTUP_FUNCTION(registerTypes)
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource((QUrl(QStringLiteral("qrc:/main.qml"))));
view.show();
return app.exec();
}
您的类型“ErrorCode”仅在线程中定义(不在主线程中)
qmlRegisterType使QObject(MyClass)类可以在QML中访问(Q_属性、Q_枚举、Q_信号、Q_插槽、Q_可调用等),但不允许在线程之间传输数据,在这种情况下,必须使用
qRegisterMetaType(“ErrorCode”)
:
main.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();
}
}
#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();
}
#include <QGuiApplication>
#include <QQuickView>
#include "MyClass.h"
static void registerTypes(){
qRegisterMetaType<MyClass::ErrorCode>("ErrorCode");
qmlRegisterType<MyClass>("MyClass", 1, 0, "MyClass");
}
Q_COREAPP_STARTUP_FUNCTION(registerTypes)
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
QQuickView view;
view.setSource((QUrl(QStringLiteral("qrc:/main.qml"))));
view.show();
return app.exec();
}
#包括
#包括
#包括“MyClass.h”
静态无效注册表类型(){
qRegisterMetaType(“错误代码”);
qmlRegisterType(“MyClass”,1,0,“MyClass”);
}
Q_COREAPP_启动功能(注册表类型)
int main(int argc,char*argv[])
{
QGUI应用程序应用程序(argc、argv);
QQuickView视图;
view.setSource((QUrl(QStringLiteral(“qrc:/main.qml”)));
view.show();
返回app.exec();
}
您从哪里获得这些信息的?我从来没有在任何文件中读到过。我认为这与此无关。创建宏Q_ENUM
是为了处理在其自身内声明/注册元类型。请注意,如果我导致调用MyClass::mainThreadError()
,则它可以正常工作。只有当信号从QThread
线程触发时,才会出现问题,例如,导致调用MyClass::otherThreadError()
。请注意qRegisterMetaType()!=qmlRegisterType()谢谢!你的开场白——这有没有记录在案?@PaulMasri Stone这并不明确,但可以从文件和错误中推断出来。