Как использовать перечисления в Qt-сигналах и слотах - программирование
Подтвердить что ты не робот

Как использовать перечисления в Qt-сигналах и слотах

У меня есть некоторые проблемы с использованием типов enum в сигналах. В основном у меня есть два класса: конечный автомат и поток, обрабатывающий конечный автомат. Когда состояние изменено, я хочу отправить сигнал с новым состоянием. Я также хочу представить состояние с помощью enum. В моем полномасштабном коде конечный автомат реализуется в отдельной общей библиотеке, но приведенный ниже код дает ту же самую ошибку.

Когда я запускаю код, я получаю следующее поведение:

[email protected]:sigenum $ ./sigenum 
Object::connect: No such slot MyThread::onNewState(state)
Test signal 
Test signal 
...

У меня есть четыре файла в моем примере кода: statemachine.h, statemachine.cpp, main.h и main.cpp. Основная функция просто запускает поток, затем поток создает экземпляр 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

И он реализован как:

// statemachine.cpp
#include <QtCore>

#include "statemachine.h"

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

Поток определяется как

// 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

И он реализован следующим образом:

// 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;
}
4b9b3361

Ответ 1

Используя полнофункциональные имена во всем мире, я получил его для работы

Если я изменил объявление stateChanged() на

signals:
    void stateChanged(StateMachine::state newState);

И регистрирует тип с помощью

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

а также использует это имя в инструкции connect

connect(myStateMachine, SIGNAL(stateChanged(StateMachine::state)),
        this, SLOT(onNewState(StateMachine::state)));

Не решил бы этого без ввода от drescherjm, спасибо: -)

Ответ 2

Я считаю, что следующее состояние не определено в вашем классе MyThread.

Используйте следующие

 connect(myStateMachine, SIGNAL(stateChanged(StateMachine::state)),
            this, SLOT(onNewState(StateMachine::state)));

Edit:

Возможно, это сработает

 connect(myStateMachine, SIGNAL(stateChanged(state)),
            this, SLOT(onNewState(StateMachine::state)));