Question

I have to create an 2 custom events. I followed this link & made my code :--
Is there a cleaner way to register Qt custom events?

Is it the right way to create & post & pass some data(Qstring) to the customized event ?

===========================================================

Edit code as per Kuba Ober sugession :---

Mainwindow.h :--

UpdateEvent *myUpdateEvent ;
ClearEvent *myClearEvent ;

Mainwindow.c :---

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    i =0;
    myUpdateEvent = new UpdateEvent("hello");
    myClearEvent  = new ClearEvent("bye");

    QCoreApplication::postEvent(this, myUpdateEvent);
    QCoreApplication::postEvent(this, myClearEvent);


}

bool MainWindow::eventFilter(QObject *obj, QEvent *event)
{

    qDebug() << "oo";
   if (UpdateEvent::is(event)) {
       UpdateEvent *tempUpdateEvent = static_cast<UpdateEvent *>(event);
       qDebug() << tempUpdateEvent->value();

   }
   else if (ClearEvent::is(event)) {
       ClearEvent *tempClearEvent = static_cast<ClearEvent *>(event);
       qDebug() << tempClearEvent->value();

   }

   return true;

}

event.h file :--

template <typename T> class StringEvent : public QEvent
{
   QString m_str;
public:
   explicit StringEvent(const QString val) : QEvent(staticType()), m_str(val)
   {
   }

   QString setvalue(QString val)
   {
       m_str = val;
   }

   QString value() const
   {
       return m_str;
   }

   static QEvent::Type staticType()
   {
      static int type = QEvent::registerEventType();
      return static_cast<QEvent::Type>(type);

   }

   static bool is(const QEvent * ev)
   {
       return ev->type() == staticType();
   }
};

class UpdateEvent : public StringEvent<UpdateEvent>
{
public:
    explicit UpdateEvent(QString val): StringEvent(val)
    {

    }

};

class ClearEvent  : public StringEvent<ClearEvent>
{
public:
    explicit ClearEvent(QString val): StringEvent(val)
    {

    }
};

why eventFilter is not triggered ? And i am not able to see debug message on postevent ?

Was it helpful?

Solution

I can only comment on the code smell of your event implementation, since it is at this point unclear why would you need to send events to an edit control within a window. The latter is bad design.

Your Event class is needlessly complicated. You should be setting up all values inside the event during construction, and they should be accessible through read-only accessors afterwards. The extra event type seems to be an unnecessary gimmick as well.

Here's how I'd do it, using a metafactory pattern (a name I just coined, perhaps there's a better/existing name for it?). This solves the need for explicit derived class constructor injection that'd be otherwise needed.

I've split up the metafactory into small constituent classes for ease of understanding.

// A type-identifier-generating wrapper for events
template <typename D> class EventWrapper : public QEvent {
public:
    EventWrapper() : QEvent(staticType()) {}
    static QEvent::Type staticType() {
        static QEvent::Type type = static_cast<QEvent::Type>(registerEventType());
        return type;
    }
    static bool is(const QEvent * ev) { return ev->type() == staticType(); }
    static D* cast(QEvent * ev) { return is(ev) ? static_cast<D*>(ev) : 0; }
};

// The generic event metafactory for C++98 (doesn't need C++11)
template <typename D, template <typename> class Carrier> class EventMF {
    class EventFwd;
    class Final;
    class FinalWrapper : public EventWrapper<EventFwd>, public virtual Final {};
public:
    // EventFwd is a class derived from Event. The EventWrapper's cast()
    // will cast to a covariant return type - the derived class. That's OK.
    typedef Carrier<FinalWrapper> Event;
private:
    class EventFwd : public Event {};
    class Final {
        friend class FinalWrapper;
        friend class Carrier<FinalWrapper>;
    private:
        Final() {}
        Final(const Final &) {}
    };
};

// A string carrier
template <typename B> class StringData : public B {
    QString m_str;
public:
    explicit StringData(const QString & str) : m_str(str) {}
    QString value() const { return m_str; }
};

// A string event metafactory
template <typename D> class StringEventMF : public EventMF<D, StringData> {};

class Update : public EventMF<Update, StringData> {}; // using generic metafactory
class Clear : public StringEventMF<Clear> {}; // using specific metafactory
#if 0
// This should fail at compile time as such derivation would produce classes with
// duplicate event types. That's what the Final class was for in the matafactory.
class Error : public Update::Event { Error() : Update::Event("") {} };
#endif

int main(int, char**)
{
    // Test that it works as expected.
    Update::Event update("update");
    Clear::Event clear("clear");
    Q_ASSERT(Update::Event::staticType() != Clear::Event::staticType());
    Q_ASSERT(Update::Event::staticType() == Update::Event::cast(&update)->staticType());
    qDebug() << Update::Event::cast(&update)->value();
    Q_ASSERT(Update::Event::cast(&clear) == 0);
    qDebug() << Clear::Event::cast(&clear)->value();
    Q_ASSERT(Clear::Event::cast(&update) == 0);
}

The Metafactory::Event classes are the custom event classes that derive from QEvent. The class hierarchy for Update::Event looks as follows (going from the least derived to most derived class):

  • EventWrapper<EventMF<...>::EventFwd>, EventMF<...>::Final (multiple inheritance)

  • EventMF<Update, StringData<Update>>::FinalWrapper

  • StringData<Update> = EventMF<Update, StringData<Update>>::Event

    with EventMF<...> being shorthand for EventMF<Update, StringData<Update>.

The line Update::Event update("update") constructs a custom string-carrying event instance, with the constructors called from the last to the first in the list above.

Since EventMF<...> is a metafactory that works at time of compilation only, there is absolutely no need for its instance to exist at runtime. Thus EventMF<...>::EventMF constructor is never called. You can enforce this invariant by deleting the constructor (declaring it private for C++98).

The use within an event handler would look like:

void MainWindow::customEvent(QEvent *event)
{
   ...
   if (Update::Event::is(event)) {
      qDebug() << Update::Event::cast(event)->value();
      ...
   }
   else if (Clear::Event::is(event)) {
      ...
   }
   ...
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top