Learn about occurred events from other class

2019-07-30 18:53发布

问题:

I have two classes:

typedef std::shared_ptr<AdaptedWidget> window_ptr;

class WindowManager
{
public:
...
private:
    std::stack<window_ptr> m_windowsStack;
}

and

class AdaptedWidget: public QWidget
{
    Q_OBJECT
public:
    AdaptedWidget(AdaptedWidget *parent = 0);
    bool event(QEvent *event);
};

bool AdaptedWidget::event(QEvent *event)
{
    if (event->type() == QEvent::NonClientAreaMouseButtonPress ||
        event->type() == QEvent::MouseButtonPress)
    {
        qDebug() << "mainwindwo press";
    }
    return QWidget::event(event);
}

I need to get information about events that happen in AdaptedWidget objects from my WindowManager object, How can I do that?

回答1:

Event filters are the Qt way to accomplish your task.

Make your WindowManager class a subclass of QObject and provide an implementation for its eventFilter() method.

After that, every time you create an AdaptedWidget use installEventFilter() to install your WindowManager instance as an event filter on it.

class WindowManager : public QObject
{
public:
...
bool eventFilter(QObject* obj, QEvent* ev);

private:
    std::stack<window_ptr> m_windowsStack;
}

and

bool WindowManager::eventFilter(QObject* obj, QEvent* ev){
    AdaptedWidget* widget= qobject_cast<AdaptedWidget*>(obj);
    if(ev->type == /*type of event you are interested in*/){
        //you can compare widget against the stack of widgets you have

        //if you want to stop widget from receiving the event you can return true
    }
    return false;
}

and when creating each AdaptedWidget instance, install the WindowManager as an event filter:

AdaptedWidget* widget= new AdaptedWidget;
widget->installEventFilter(/*your WindowManager instance*/);


回答2:

The AdaptedWidget class should have a signal that indicates a mouse press, e.g.

class AdaptedWidget : ... {
  Q_OBJECT
  ...
public:
  Q_SIGNAL void mousePress(const QPoint &);
};

bool AdaptedWidget::event(QEvent *event)
{
    if (event->type() == QEvent::NonClientAreaMouseButtonPress ||
        event->type() == QEvent::MouseButtonPress)
    {
        auto ev = static_cast<QMouseEvent*>(event);
        emit mousePress(ev->pos());
        qDebug() << "mainwindow press";
    }
    return QWidget::event(event);
}

Another approach is to use event filters, but that unnecessarily tightly couples the two classes.