Tengo algunos problemas con el uso de tipos de señales enum
. Básicamente tengo dos clases, una máquina de estados y un hilo que maneja la máquina de estados. Cuando se cambia el estado, quiero enviar una señal con el nuevo estado. También quiero representar al estado usando un enum
. En mi código completo, la máquina de estados se implementa en una biblioteca compartida separada, pero el código a continuación proporciona el mismo error exacto.Cómo usar enumeraciones en las señales y ranuras Qt
Cuando ejecuto el código me sale el siguiente comportamiento:
[email protected]:sigenum $ ./sigenum
Object::connect: No such slot MyThread::onNewState(state)
Test signal
Test signal
...
Tengo cuatro archivos en mi código de ejemplo: statemachine.h
, statemachine.cpp
, main.h
y main.cpp
. La función principal simplemente inicia el hilo, el hilo crea una instancia del StateMachine
y procesa las señales del StateMachine
. Soy bastante nuevo en Qt, así que me quedé un poco perplejo cuando me di cuenta de que tenía que encerrar la enumeración con Q_ENUMS
y registrarla en el sistema de tipos. Así que es completamente posible que haya cometido un error de novato
El código siguiente es un poco largo, pero quería que fuera lo más similar posible a mi código real.
statemachine.h
parece:
// 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
Y se implementa como:
// statemachine.cpp
#include <QtCore>
#include "statemachine.h"
void StateMachine::setState(state newState)
{
emit stateChanged(newState);
emit testSignal();
}
El hilo se define como
// 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
Y se implementa de la siguiente manera:
// 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;
}
Para el registro, la razón por la que esto resuelve el problema es que el sistema de metaobjetos está decidiendo la compatibilidad señal/ranura en base a comparaciones de cadenas (normalizadas). No "sabe" que 'StateMachine :: state' y' state' se refieren al mismo tipo en este contexto. – rohanpm
No he necesitado qRegisterMetaType usando Qt 4.8, solo nombres completamente calificados en todas partes. – kikeenrique
Obtuve un ejemplo similar de trabajo sin llamar explícitamente a 'qRegisterMetaType()' simplemente eliminando el punto y coma de la línea 'Q_DECLARE_METATYPE (StateMachine :: state)' – user666412