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

Kot*_*tte 16 c++ enums qt

enum在信号中使用类型时遇到了一些麻烦.基本上我有两个类,一个状态机和一个处理状态机的线程.当状态改变时,我想发送一个具有新状态的信号.我也想用一个代表国家enum.在我的完整代码中,状态机是在一个单独的共享库中实现的,但下面的代码给出了完全相同的错误.

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

kotte@EMO-Ubuntu:sigenum $ ./sigenum 
Object::connect: No such slot MyThread::onNewState(state)
Test signal 
Test signal 
...
Run Code Online (Sandbox Code Playgroud)

我在我的示例代码四个文件:statemachine.h,statemachine.cpp,main.hmain.cpp.main函数只是启动线程,然后线程创建一个实例StateMachine并处理来自的线程StateMachine.我对Qt很陌生,所以当我意识到你必须将enum包含在内Q_ENUMS并用类型系统注册它时,我有点困惑.所以我完全有可能犯了一些菜鸟错误

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

statemachine.h 好像:

// 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
Run Code Online (Sandbox Code Playgroud)

它实现为:

// statemachine.cpp
#include <QtCore>

#include "statemachine.h"

void StateMachine::setState(state newState)
{
    emit stateChanged(newState);
    emit testSignal();
}
Run Code Online (Sandbox Code Playgroud)

该线程定义为

// 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
Run Code Online (Sandbox Code Playgroud)

它实现如下:

// 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;
}
Run Code Online (Sandbox Code Playgroud)

Kot*_*tte 17

通过在任何地方使用完全限定的名称我得到它的工作

如果我将声明更改stateChanged()

signals:
    void stateChanged(StateMachine::state newState);
Run Code Online (Sandbox Code Playgroud)

并注册类型

qRegisterMetaType<StateMachine::state>("StateMachine::state");
Run Code Online (Sandbox Code Playgroud)

并在connect声明中使用此名称

connect(myStateMachine, SIGNAL(stateChanged(StateMachine::state)),
        this, SLOT(onNewState(StateMachine::state)));
Run Code Online (Sandbox Code Playgroud)

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

  • 为了记录,解决该问题的原因是元对象系统基于(标准化的)字符串比较来决定信号/时隙兼容性.它并不"知道"`StateMachine :: state`和`state`在这个上下文中引用相同的类型. (4认同)

dre*_*rjm 5

我相信以下状态未在您的 MyThread 类中定义。

使用以下

 连接(我的状态机,信号(状态改变(状态机::状态)),
            这,插槽(onNewState(StateMachine::state)));

编辑:

也许这会奏效

 连接(我的状态机,信号(状态改变(状态)),
            这,插槽(onNewState(StateMachine::state)));