2011-04-19 98 views
7

我試圖動態創建插槽並將它們連接起來。我能夠動態地創建pushButton並將它們與現有的插槽連接起來。但是如果我有一個具有一些成員函數的類,並且我想將這些函數用作插槽,那該怎麼辦?在Qt中創建動態插槽

從一般的角度來看,我想創建一個給定函數指針的插槽生成模板。這使我們可以在不更改現有代碼的情況下創建插槽,而無需使用MOC重新編譯。 如果這沒有道理讓我知道。謝謝。

-CV

回答

9

它確實很有意義。我認爲QSignalMapper不是你想要的。如果你的函數沒有爭論,也許這樣的事情就夠了:

class SlotForwarder : public QObject 
{ 
    Q_OBJECT 

public: 

    typedef void (*Function)(); // or whatever. I never get this syntax right... 

    SlotForwarder(Function function, QObject* parent = 0) 
     : QObject(parent) 
     , m_fptr(function) 
    {} 

public slots: 

    void forward() 
    { 
     m_fptr(); 
    } 

private: 

    Function m_fptr; 
}; 

爲您創建一個要封裝並連接到forward像往常一樣每個功能。現在


,如果他們紛紛議論,也許這Qt的季度文章可能有所幫助。

Dynamic Signals and Slots by Eskil A. Blomfeldt

該技術涉及重新實現自己qt_metacall方法。該方法具有這樣的簽名:

int QObject::qt_metacall(QMetaObject::Call call, int id, void **arguments) 

呼叫是那種metacall的:插槽,信號,財產讀或寫,等,每個插槽有一個ID。參數在參數數組內打包(通過值或指針)。讀取moc生成的代碼是理解它如何工作的好方法。

關於原始函數簽名的數據僅在編譯期間可用,但插槽在運行時解析。由於這種不匹配,你需要將這些函數包裝成一個模板適配器類型,它爲你的實現qt_metacall提供了一個常量接口,並將arguments數組轉換成函數可以理解的東西(參見Python unpack運算符)。 Boost.Signals是那種template hackery

+0

感謝您的代碼。這應該適用於普通功能,但不適用於成員功能。你知道有一種方法可以爲類成員函數做到這一點嗎? – blueskin 2011-04-20 16:38:32

+0

謝謝andref。我找到了使用tr1 :: bind的成員函數部分。我已經在下面發佈了我的代碼。一旦我有一個用於創建動態UI的小應用程序(包括動態信號/插槽連接),我就會發佈一個鏈接。 – blueskin 2011-04-21 00:46:34

2

的andref的代碼的延續,以便使用任何成員函數爲槽

class SlotForwarder : public QObject 
    { 
     Q_OBJECT 

    public: 

     typedef void (*Function)(); 

     SlotForwarder(Function function, QObject* parent = 0) 
      : QObject(parent) 
      , m_fptr(function) 
     {} 

    public slots: 

     void forward() 
     { 
      m_fptr(); 
     } 

    private: 

     Function m_fptr; 
    }; 

    int main(){ 
     QApplication a(argc, argv); 
     MyClass myClassObject; //contains a function called MemberFunc 
     //create a slotforwarder object so 
     SlotForwarder *memberFuncSlot = new SlotForwarder (std::tr1::bind(&MyClass::MemberFunc, &myClassObject)); 
     QObject::connect(ui.button,SIGNAL(clicked()),memberFuncSlot,SLOT(forward()); 
    } 
+0

哇! 'tr1 :: bind'很棒,我完全忘記了它。 – andref 2011-04-21 01:23:46

+0

是的,我也忘了 – blueskin 2011-04-21 13:56:56

+0

有趣的方法,但是你什麼時候刪除正常程序中的轉發器。我想一個聰明的指針會更明智 – Martin 2012-10-15 19:53:18