2

I want to send some custom events between two Qt objects, but without making a relation between them. Normally in Qt we can send custom events (QApplication::sendEvent) but we must specify a pointer to receiver object! But when that two objects are in different scope (i.e. some widget, and receiver is some object managing database) sharing a pointer to receiver could be problematic.

I created an event dispatcher object for handling custom evens. Its operation is very simple - at the one side, Qt object can send custom event to dispatcher (dispatcher is a receiver), and second object (receiver) subscribes to receive that custom events. Both objects doesn't know about each other, but dispatcher must be globally available from any place in code (which is not a huge problem). Example simplified code:

EventDispatcher.h

class EventDispatcher : public QObject
{
public:
    EventDispatcher() = default;
    bool event(QEvent* e) override;

    void registerObj(QObject* obj)
    {
        subscribers.push_back(obj);
    }

private:
    std::vector<QObject*> subscribers;
};

EventDispatcher.cpp

bool EventDispatcher::event(QEvent *e)
{
    if(e->type() == QCustomEvent::type())
    {
        //getValue is a specific method of QCustomEvent
        qDebug() << "custom event received. Value: " << ((QCustomEvent*)e)->getValue();
        for(auto* s : subscribers)
            QApplication::sendEvent(s, e);
        return true;
    }
    return QObject::event(e);
}

Usage - sending events:

//QCustomEvent inherits from the QEvent
QCoreApplication::sendEvent(g_eventDispatcherInstance, new QCustomEvent());

Usage - registering:

g_evd->registerObj(ui->widget_4);

//we can receive and handle that custom event in widget_4 class in bool event(QEvent* ev) override; method

However i have a belief that it can be done simpler, without making a intermediate dispatcher class, using only Qt classes, and without coupling both of them - sander and receiver. Hmm, but looking at this question: Post events without specifying target object in Qt , looks like it is not so trivial, and making some kind of dispatcher is unavoidable :-|

pio
  • 21
  • 2
  • 1
    Any specific reason you cannot use signals and slots for this? There you can use QObject::connect to hook the two together. – Botje Mar 22 '23 at 09:59
  • 1
    @Botje but with signals and slots you still need to bring the both objects to the same scope to be able to establish the connection. I understand the question aims at communication of two totally distant objects. – HiFile.app - best file manager Mar 22 '23 at 11:04

1 Answers1

2

How about one object sending a custom event to qApp object (or QCoreApplication::instance()). And the other object can install event filter on qApp object and process the custom event once it is intercepted. The two objects (the event sender and the event processor) do not need to know of each other. And qApp will just ignore the custom event if not processed by the event filter. And all you need is just to implement event filter for the processor object. This is very simple.