2012-09-11 42 views
16

Tôi gặp sự cố khi sử dụng các loại tín hiệu enum. Về cơ bản, tôi có hai lớp, một máy trạng thái và một luồng xử lý máy trạng thái. Khi trạng thái được thay đổi, tôi muốn gửi tín hiệu với trạng thái mới. Tôi cũng muốn đại diện cho tiểu bang bằng cách sử dụng số enum. Trong mã đầy đủ của tôi, máy trạng thái được thực hiện trong một thư viện chia sẻ riêng biệt, nhưng đoạn mã dưới đây đưa ra cùng một lỗi chính xác.Cách sử dụng enums trong tín hiệu và khe Qt

Khi tôi chạy mã tôi nhận được các hành vi sau đây:

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

Tôi có bốn tập tin trong mẫu mã của tôi: statemachine.h, statemachine.cpp, main.hmain.cpp. Hàm main chỉ đơn giản là bắt đầu luồng, sau đó tạo một thể hiện của StateMachine và xử lý các tín hiệu từ StateMachine. Tôi khá mới để Qt, vì vậy tôi là một chút bối rối khi tôi nhận ra rằng bạn phải kèm theo enum với Q_ENUMS và đăng ký nó với hệ thống kiểu. Vì vậy, hoàn toàn có thể là tôi đã phạm một số sai lầm tân binh

Đoạn mã dưới đây hơi dài, nhưng tôi muốn nó giống như mã thực của tôi càng tốt.

statemachine.h trông giống như:

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

Và nó được thực hiện như:

// statemachine.cpp 
#include <QtCore> 

#include "statemachine.h" 

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

Các chủ đề được định nghĩa là

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

Và nó được thực hiện như sau:

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

Trả lời

15

Bằng cách sử dụng tên đầy đủ ở khắp mọi nơi tôi đã nhận nó làm việc

Nếu tôi thay đổi tuyên bố của stateChanged() đến

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

Và đăng ký kiểu với

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

và cũng sử dụng tên này vào báo cáo kết connect

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

Sẽ không đã giải quyết này mà không có đầu vào từ drescherjm, nhờ :-)

+4

Đối với hồ sơ, lý do tại sao điều này giải quyết vấn đề là hệ thống metaobject quyết định khả năng tương thích tín hiệu/khe dựa trên các so sánh chuỗi (chuẩn hóa). Nó không "biết" rằng 'StateMachine :: state' và' state' tham chiếu đến cùng một kiểu trong ngữ cảnh này. – rohanpm

+0

Tôi không cần qRegisterMetaType bằng cách sử dụng Qt 4.8, chỉ cần tên đủ điều kiện ở khắp mọi nơi. – kikeenrique

+0

Có một ví dụ tương tự làm việc mà không cần gọi một cách rõ ràng 'qRegisterMetaType()' chỉ bằng cách loại bỏ dấu chấm phẩy khỏi dòng 'Q_DECLARE_METATYPE (StateMachine :: state)' – user666412

4

Tôi tin rằng sau đây là trạng thái không được xác định trong lớp MyThread của bạn.

Sử dụng sau

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

Edit:

lẽ điều này sẽ làm việc

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

Sau đó tôi nhận được 'Không có tín hiệu như vậy StateMachine :: stateChanged (StateMachine :: state)' thay vì – Kotte

+1

Bạn đã thử sử dụng typedef trong giao diện MyThread của bạn.Những gì tôi có nghĩa là typedef StateMachine :: nhà nước nhà nước; – drescherjm

+0

Hmm, nhưng nó đã dẫn tôi đến giải pháp, cảm ơn :) – Kotte

Các vấn đề liên quan