2

我必须创建 2 个自定义事件。我点击了这个链接并编写了我的代码:--
有没有更简洁的方法来注册 Qt 自定义事件?

它是创建&发布&传递一些数据(Qstring)到自定义事件的正确方法吗?

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

根据 Kuba Ober 的建议编辑代码:---

主窗口.h :--

UpdateEvent *myUpdateEvent ;
ClearEvent *myClearEvent ;

主窗口.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 文件:--

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)
    {

    }
};

为什么 eventFilter 没有被触发?而且我无法在 postevent 上看到调试消息?

4

1 回答 1

0

我只能评论您的事件实现的代码味道,因为目前尚不清楚为什么需要将事件发送到窗口中的编辑控件。后者是糟糕的设计。

您的 Event 类是不必要的复杂。您应该在构造期间设置事件内的所有值,并且之后应该可以通过只读访问器访问它们。额外的事件类型似乎也是一个不必要的噱头。

这就是我的做法,使用元工厂模式(我刚刚创造的一个名字,也许它有一个更好/现有的名字?)。这解决了对显式派生类构造函数注入的需要,否则需要。

为了便于理解,我将元工厂分成了小的组成类。

// 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);
}

这些Metafactory::Event类是派生自QEvent自定义事件类。Update::Event 的类层次结构如下所示(从最小派生类到最大派生类):

  • EventWrapper<EventMF<...>::EventFwd>, EventMF<...>::Final(多重继承)

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

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

    EventMF<...>的简写EventMF<Update, StringData<Update>

该行Update::Event update("update")构造了一个自定义的带有字符串的事件实例,构造函数在上面的列表中从最后一个调用到第一个。

由于EventMF<...>是一个仅在编译时工作的元工厂,因此绝对不需要它的实例在运行时存在。因此EventMF<...>::EventMF构造函数永远不会被调用。您可以通过删除构造函数(将其声明为 C++98 私有)来强制执行此不变量。

在事件处理程序中的使用如下所示:

void MainWindow::customEvent(QEvent *event)
{
   ...
   if (Update::Event::is(event)) {
      qDebug() << Update::Event::cast(event)->value();
      ...
   }
   else if (Clear::Event::is(event)) {
      ...
   }
   ...
}
于 2013-10-03T16:22:37.517 回答