2012-09-11 31 views
16

我在使用enum類型的信號時遇到了一些問題。基本上我有兩個類,一個狀態機和一個處理狀態機的線程。當狀態改變時,我想發送一個新狀態的信號。我也想用enum代表國家。在我完整的代碼中,狀態機在單獨的共享庫中實現,但下面的代碼給出了完全相同的錯誤。如何在Qt信號和插槽中使用枚舉

當我運行代碼,我得到了以下行爲:

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

我已經在我的樣本代碼四個文件:statemachine.hstatemachine.cppmain.hmain.cpp。主函數只是啓動線程,然後線程創建StateMachine的實例並處理來自StateMachine的信號。我對Qt非常陌生,所以當我意識到必須將枚舉與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; 
} 

回答

15

通過使用完全合格的名字無處不在我得到它的工作

如果我改變聲明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輸入,感謝:-)

+4

爲了記錄,解決此問題的原因是元對象系統正在根據(標準化)字符串比較來決定信號/插槽的兼容性。它不會「知道」StateMachine :: state和state在這個上下文中引用了相同的類型。 – rohanpm

+0

我不需要QRegisterMetaType使用Qt 4.8,只是完全限定的名字無處不在。 – 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