簡體   English   中英

訂閱另一類的事件

[英]Subscribing to events of one class in other

在這里的C ++程序中,我創建了一個圖像按鈕控件,該控件具有一個圖像按鈕並具有點擊測試功能,以判斷鼠標是否在視頻中單擊。

class ImageButton{
public:
ImageButton(int xPos, int yPos, int width, int height);
virtual void onMousePress(); //triggered internally if the mouse clicked inside the button
virtual void onMousePressOutside() //triggered internally if the mouse clicked outside the button
private:
bool hitTest(int, int); //check if is in bounds
};

現在,還有另外一個我必須利用此ImageButton控件的地方。 因為我來自C#,所以我記得很容易使用控件並訂閱它們的事件,例如

btnControl.Click += new MouseClickEventHandler(Sender e, EVentArgs e)

我剛剛開始使用Poco庫在C ++中獲得類似的事件訂閱功能,但是想問我如何創建可以在我的第二個類中訂閱的事件,並且ImageButton onMousePress會觸發這個第二個類中的訂閱函數?

一種方法是應用觀察者設計模式。 例如,ImageButton類接收事件,感興趣的客戶端對象將向ImageButton注冊。 事件發生時,ImageButton會通知所有注冊的客戶端,這些客戶端依次負責對事件進行適當的響應。

另一種類似的方法是,如果您的庫提供信號/插槽機制,則使用它。 根據我自己的經驗,我更喜歡顯式觀察者模式應用而不是信號和插槽,因為程序中的執行流是顯式可見的。 當廣泛使用單/槽機制時,某些時候事情開始神奇地發生,並且告訴程序正在做的事情很容易。

多年來,我們一直在產品中的GUI上使用支持信號和插槽的Qt。 過去,信號和插槽無處不在。 但是,出於上述原因,我們已更改了政策,使其僅在嚴格的GUI代碼中使用,而不再讓其傳播到業務代碼中。

為解決上述問題,我將做以下事情,檢查是否對您有幫助。

class EventData
{
};

// base class for all the secondary classes which expect to get a call back control from
// the first object where we perform hit-test.

class EventHandler
{
public:
virtual void performAction(EventData* ed) = 0;
};

// Second class constructor can register itself to your first object.

class SecondClass : public EventHandler
{
public:
    SecondClass()
    { 
        ImageButton::registerForEventAction(*this);
    }
    void performAction(EventData* ed)
    {
       // this method gets called back when a hit test gets passed and we will get control
       // at the same time at second object to perform necessary operation.
    }
};

// ... extending your first class with below method, and another member variable.

class ImageButton 
{
// extension to base definition of ImageButton .. assuming namespace kind of convention 
// just for simplicity and completeness

private:
std::vector<EventHandler&> registeredHandlers;

public:
static void ImageButton::registerForEventAction(EventHandler& eh)
{
  // For Simplicity I'm assuming your First class object is singleton, if not you need to
  // figure out how you can get access to first object in your second class.

 ImageButton::getInstance().registeredHandlers.push_back(eh);
}

bool hitTest(int, int)
{
bool success = true; 
// ideally above variable should be set to false at the start setting it to true for 
// readability

   if (success) {
        for (std::vector<EventHandler&>::iterator i = registeredHandlers.begin(); i !=       registeredHandlers.end(); ++i) {
        // pass on any event data if you need to.
           (*i).performAction(NULL);
        }
    } // End of if
}// End of method
}; // End of Class Definition

如果要使用類似於委托的內容,則應該很接近:

#include <functional>
//typedef void (*VoidCallback)(void); // only works with static member functions
typedef std::tr1::function<void (void)> VoidCallback;

class ImageButton{
public:
// ...
    VoidCallback onMousePress;
    VoidCallback onMousePressOutside;
private:
    bool hitTest(int x, int y) { onMousePress(); return true; }
};

class ImageButtonWrapper {
private:
    ImageButton m_btn;
    static void foo() { printf("foo happened\n"); }
    void bar() { printf("this bar happened\n"); }
public:
    ImageButtonWrapper() : m_btn(0,0,100,100) {
        m_btn.onMousePress = &foo;
        m_btn.onMousePressOutside = std::bind(&ImageButtonWrapper::bar, this);
    }
};

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM