2012-09-11 22 views
16

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; 
} 

Respuesta

15

Mediante el uso de nombres completos en todas partes lo tengo para trabajar

Si cambio la declaración de stateChanged() a

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

y registra el tipo con

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

y también utiliza este nombre en la declaración connect

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

no se habría resuelto este sin el aporte de drescherjm, gracias :-)

+4

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

+0

No he necesitado qRegisterMetaType usando Qt 4.8, solo nombres completamente calificados en todas partes. – kikeenrique

+0

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

4

Creo que el siguiente es el estado no está definido en su clase MyThread.

Usar la siguiente

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

Editar:

Tal vez esto funcionará

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

Luego aparece 'No hay tal señal StateMachine :: stateChanged (StateMachine :: state)' en su lugar – Kotte

+1

¿Has probado? usando un typedef en tu interfaz MyThread.Lo que quiero decir es typedef StateMachine :: state state; – drescherjm

+0

Hmm, pero me llevó a la solución, gracias :) – Kotte

Cuestiones relacionadas