2012-12-02 212 views
1

我有一個用例操作在每個運行時初始化應用程序數據時的用例。在此表示的行爲是我的示例代碼:當調用時更改插槽中的信號插槽連接

SignalSlotChange.h

#ifndef SIGNALSLOTCHANGE_H 
#define SIGNALSLOTCHANGE_H 

#include <QtGui> 

class SignalSlotChange : public QWidget 
{ 
Q_OBJECT 

public: 
    SignalSlotChange(QWidget *parent = 0); 

private slots: 
    void firstCall(); 
    void secondCall(); 

private: 
    QPushButton *button; 

}; 

#endif // SIGNALSLOTCHANGE_H 

SignalSlotChange.cpp

#include "SignalSlotChange.h" 

SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent) 
{ 
    button = new QPushButton("Messgage", this); 
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(firstCall())); 
    show(); 
} 

void SignalSlotChange::firstCall() 
{ 
    QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton); 
    // Change the signal-slot connection to secondCall() 
    QObject::disconnect(button, SIGNAL(clicked()), this, SLOT(firstCall())); 
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(secondCall())); 
} 

void SignalSlotChange::secondCall() 
{ 
    QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton); 
} 


int main(int argc, char *argv[]) 
{ 
    QApplication app(argc, argv); 
    SignalSlotChange ssc; 
    return app.exec(); 
} 

當按下按鈕,然後初始化插槽firstCall()被稱爲。它將信號插槽連接更改爲secondCall()以用於後續信號。

我這樣做的問題是它高度耦合,並要求該插槽知道確切的方法和信號來改變它。

QObject::sender()我會知道發件人的來源,但不知道它的信號,我只知道一個發件人碰巧發出了這個信號。

我可以用布爾值first_call來做到這一點,但是會對所有後續調用進行布爾值檢查,這是我想避免的,因此也是這個問題。

SignalSlotChange.h

#ifndef SIGNALSLOTCHANGE_H 
#define SIGNALSLOTCHANGE_H 

#include <QtGui> 

class SignalSlotChange : public QWidget { 
Q_OBJECT 


public: 
    SignalSlotChange(QWidget *parent = 0); 

private slots: 
    void callCall(); 

private: 
    void (SignalSlotChange::* delegate)(); 

    void firstCall(); 
    void secondCall(); 

    QPushButton *button; 

}; 

#endif // SIGNALSLOTCHANGE_H 

SignalSlotChange.cpp

#include "SignalSlotChange.h" 

SignalSlotChange::SignalSlotChange(QWidget *parent) : QWidget(parent) { 
    delegate = &SignalSlotChange::firstCall; 

    button = new QPushButton("Messgage", this); 
    QObject::connect(button, SIGNAL(clicked()), this, SLOT(callCall())); 
    show(); 
} 

void SignalSlotChange::callCall() { 
    (this->*delegate)(); 
} 

void SignalSlotChange::firstCall() { 
    QMessageBox::information(this, "SignalSlotChange", "First call", QMessageBox::Ok, QMessageBox::NoButton); 

    // Change the effective signal-slot connection to secondCall() 
    delegate = &SignalSlotChange::secondCall; 
} 

void SignalSlotChange::secondCall() { 
    QMessageBox::information(this, "SignalSlotChange", "Second call", QMessageBox::Ok, QMessageBox::NoButton); 
} 


int main(int argc, char *argv[]) { 
    QApplication app(argc, argv); 
    SignalSlotChange ssc; 
    return app.exec(); 
} 

I:

+1

您只關心執行速度嗎?如果是這樣,我仍然會選擇保持信號/插槽連接完好的方法,並使用first_call布爾值來區分第一個和所有後續調用。不要高估檢查布爾值的「開銷」 - 在典型的UI應用程序中,您永遠不會意識到此檢查。當然,如果你有一些獨特的特殊要求,可能會有所不同...... –

+0

在正確的心態中,任何人都會這樣做,這就是爲什麼我提到它,以節省人們把時間作爲答案。從學習的角度來看這個問題,如果給定的應用程序明確要求。 – Xolve

+0

足夠公平:)看到我的答案下面的一個有點不同的解決方案。 –

回答

1

一種略爲不同的溶液可以通過使用一個指針到構件的方法來實現我不確定這是否是從脫鉤角度來看更好的解決方案,但是advan有趣的是,該機制不需要知道實際觸發的插槽的任何信息。實現「方法切換」的完整邏輯封裝在SignalSlotChange類中。 callCall()插槽可以連接到任何其他兼容信號,方法開關仍然可以工作,不需要更改代碼。

+0

不錯!但是這會讓大型代碼庫混淆不清。 – Xolve