首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何在Qt信号和槽中使用枚举

如何在Qt信号和槽中使用枚举
EN

Stack Overflow用户
提问于 2012-09-11 19:29:05
回答 2查看 21.7K关注 0票数 19

我在信号中使用enum类型时遇到了一些问题。基本上我有两个类,一个状态机和一个处理状态机的线程。当状态改变时,我想发送一个带有新状态的信号。我还希望使用enum来表示状态。在我的完整代码中,状态机是在一个单独的共享库中实现的,但是下面的代码给出了完全相同的错误。

当我运行代码时,我得到了以下行为:

代码语言:javascript
复制
kotte@EMO-Ubuntu:sigenum $ ./sigenum 
Object::connect: No such slot MyThread::onNewState(state)
Test signal 
Test signal 
...

我的示例代码中有四个文件:statemachine.hstatemachine.cppmain.hmain.cpp。main函数只是启动线程,然后线程创建StateMachine的一个实例并处理来自StateMachine的信号。我是Qt的新手,所以当我意识到必须用Q_ENUMS封装枚举并将其注册到类型系统时,我有点困惑。所以我完全有可能犯了一个新手的错误

下面的代码有点长,但我希望它尽可能地与我的真实代码相似。

statemachine.h看起来像这样:

代码语言:javascript
复制
// statemachine.h
#ifndef _STATEMACHINE_H
#define _STATEMACHINE_H

#include <QtCore>

class StateMachine : public QObject
{
    Q_OBJECT
    Q_ENUMS(state)

public:
    enum state {S0, S1, S2};

    void setState(state newState);

signals:
    void stateChanged(state newState);
    void testSignal(void);
};

Q_DECLARE_METATYPE(StateMachine::state);

#endif

并且它被实现为:

代码语言:javascript
复制
// statemachine.cpp
#include <QtCore>

#include "statemachine.h"

void StateMachine::setState(state newState)
{
    emit stateChanged(newState);
    emit testSignal();
}

该线程被定义为

代码语言:javascript
复制
// main.h
#ifndef _MAIN_H
#define _MAIN_H

#include <QtCore>

#include "statemachine.h"

class MyThread : public QThread
{
    Q_OBJECT

private:
    void run(void);

private slots:
    void onNewState(StateMachine::state);
    void onTestSignal(void);

private:
    StateMachine *myStateMachine;
};

#endif

其实现方式如下:

代码语言:javascript
复制
// main.cpp
#include <QtCore>
#include <QApplication>

#include "statemachine.h"
#include "main.h"

void MyThread::run()
{
    myStateMachine = new StateMachine();

    qRegisterMetaType<StateMachine::state>("state");

    // This does not work
    connect(myStateMachine, SIGNAL(stateChanged(state)),
            this, SLOT(onNewState(state)));

    // But this does...
    connect(myStateMachine, SIGNAL(testSignal()),
            this, SLOT(onTestSignal()));

    forever {
        // ...
        myStateMachine->setState(StateMachine::S0);
    }
}

void MyThread::onTestSignal()
{
    qDebug() << "Test signal";
}

void MyThread::onNewState(StateMachine::state newState)
{
    qDebug() << "New state is:" << newState;
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2012-09-11 19:49:01

通过在任何地方使用完全限定的名称,我让它正常工作

如果我将stateChanged()的声明更改为

代码语言:javascript
复制
signals:
    void stateChanged(StateMachine::state newState);

并将该类型注册到

代码语言:javascript
复制
qRegisterMetaType<StateMachine::state>("StateMachine::state");

,并在connect语句中使用此名称。

代码语言:javascript
复制
connect(myStateMachine, SIGNAL(stateChanged(StateMachine::state)),
        this, SLOT(onNewState(StateMachine::state)));

如果没有drescherjm的输入,就不会解决这个问题,谢谢:-)

票数 21
EN

Stack Overflow用户

发布于 2018-10-20 06:46:24

你应该去掉SIGNALSLOT,因为Qt可以在编译时检测到不匹配。您还可以通过使用Q_ENUM而不是Q_ENUMS来避免使用Q_DECLARE_METATYPEqRegisterMetaType() -这是在Qt5.5中引入的,最后,enum classenum的强类型版本

代码语言:javascript
复制
// statemachine.h
#ifndef _STATEMACHINE_H
#define _STATEMACHINE_H

#include <QtCore>

class StateMachine : public QObject
{
    Q_OBJECT
    Q_ENUM(state)

public:
    enum class state {S0, S1, S2};

    void setState(state newState);

signals:
    void stateChanged(state newState);
    void testSignal(void);
};

#endif

// main.cpp
#include <QtCore>
#include <QApplication>

#include "statemachine.h"
#include "main.h"

void MyThread::run()
{
    myStateMachine = new StateMachine();

    connect(myStateMachine, &StateMachine::stateChanged, this, &MyThread::NewState);

    connect(myStateMachine, &StateMachine::testSignal, this, &MyThread::onTestSignal);

    forever {
        // ...
        myStateMachine->setState(StateMachine::S0);
    }
}
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/12368712

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档