2012-09-11 2 views
16

신호에 enum 유형을 사용할 때 약간의 문제가 있습니다. 기본적으로 상태 시스템과 상태 시스템을 처리하는 스레드라는 두 개의 클래스가 있습니다. 상태가 변경되면 새로운 상태로 신호를 보내려고합니다. 또한 enum을 사용하여 상태를 나타내려고합니다. 내 완전 한 코드에서 상태 시스템은 별도의 공유 라이브러리에 구현되지만 아래 코드는 똑같은 오류를 제공합니다.Qt 신호 및 슬롯에서 enum을 사용하는 방법

나는 다음과 같은 동작을 얻을 코드를 실행하면 :

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

내 샘플 코드에서 네 개의 파일이 있습니다 statemachine.h, statemachine.cpp, main.hmain.cpp을. main 함수는 단순히 스레드를 시작하고 스레드는 StateMachine의 인스턴스를 만들고 StateMachine의 신호를 처리합니다. Qt를 처음 접했기 때문에 열거 형을 Q_ENUMS으로 묶고 유형 시스템에 등록해야한다는 것을 깨달았을 때 의아해했습니다. 그래서 신참 실수를 저질렀을 가능성이 충분합니다.

아래의 코드는 약간 길지만 가능한 한 실제 코드와 비슷하게 만들고 싶었습니다. 스레드가

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

으로 정의된다 그리고이 구현

// statemachine.cpp 
#include <QtCore> 

#include "statemachine.h" 

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

다음과 같습니다 :

// 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.h 보인다

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

답변

15

를 작동합니다 stateChanged() ~

의 선언
signals: 
    void stateChanged(StateMachine::state newState); 

또한

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

와 함께 유형

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

이 drescherjm의 입력없이이 문제를 해결하지 않을까요 감사도 :-) connect 문에이 이름을 사용 등록

+4

기록상, 이것이 문제를 해결하는 이유는 메타 객체 시스템이 (정규화 된) 문자열 비교를 기반으로 신호/슬롯 호환성을 결정하기 때문입니다. StateMachine :: state와 state는이 문맥에서 같은 타입을 참조한다는 것을 "알지 못한다". – rohanpm

+0

Qt 4.8을 사용하는 qRegisterMetaType은 필요하지 않았습니다. 어디에서나 정규화 된 이름을 사용했습니다. – kikeenrique

+0

'Q_DECLARE_METATYPE (StateMachine :: state)'줄에서 세미콜론을 제거하면'qRegisterMetaType()'을 명시 적으로 호출하지 않고도 비슷한 예제를 사용할 수 있습니다. – user666412

4

다음은 상태가 MyThread 클래스에 정의되어 있지 않습니다.

를 사용하여 다음과 같은

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

편집 : 나는를 변경하는 경우

를 작동하는 데있어

어쩌면이 모든 곳에서 정규화 된 이름을 사용하여

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

그럼'신호가 없습니다 StateMachine :: stateChanged (StateMachine :: state)' – Kotte

+1

시도해 보았습니까 MyThread 인터페이스에서 typedef를 사용합니다.내 말은 typedef StateMachine :: state 상태입니다. – drescherjm

+0

흠,하지만 솔루션, 고마워했다. – Kotte