c # — подписка на события одного класса в другом

Здесь, в моей программе на 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 ++, но хотел спросить, как я могу создать такое событие, которое можно подписать во втором классе и onMousePress из ImageButton запускает подписанную функцию в этом втором классе?

0

Решение

Одним из способов будет применение шаблона проектирования наблюдателя. Например, класс ImageButton получает события, а заинтересованные объекты клиента регистрируются в ImageButton. При возникновении события ImageButton уведомляет всех зарегистрированных клиентов, которые, в свою очередь, берут на себя ответственность за реагирование на событие по своему усмотрению.

Еще один похожий подход — использовать механизм сигнал / слот, если ваша библиотека предоставляет его. Исходя из собственного опыта, я предпочитаю явное применение шаблона наблюдателя вместо сигналов и слотов, потому что поток выполнения в программе явно виден. При широком использовании механизма сингла / слота, в какой-то момент все начинает происходить магическим образом, и неясно, что делает программа.

Мы использовали Qt, который поддерживает сигналы и слоты, для GUI в нашем продукте в течение многих лет. В прошлом сигналы и слоты использовались повсеместно. Но изменили нашу политику, чтобы использовать ее только в строго графическом коде и не позволять ей распространяться в бизнес-коде по причинам, указанным выше.

0

Другие решения

для решения вышеизложенного я бы сделал следующее, проверьте, поможет ли это вам.

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
0

Если вы хотите использовать что-то похожее на делегатов, это должно быть довольно близко:

#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);
}
};
0
По вопросам рекламы [email protected]