Qt 学习之路 2(23):自定义事件

那部分将作为Qt事件部分的达成。大家在前面早已从大意上上询问了Qt的平地风波机制。下边要说的是如何自定义事件。

Qt 学习之路 2(23):自定义事件

 豆子  2012年10月23日  Qt 学习之路
2  21条评论

固然 Qt
已经提供了比比较多风云,但对此进一步波谲云诡的急需来讲,有限的平地风波都以非常不够的。比如,作者要援助一种新的道具,那个装置提供一种全新的交互方式,那么,这种事件怎么样管理啊?所以,允许创设本身的平地风波类型也就从趋势看必须行动。即正是不说这种特别极端的例子,在八线程的次第中,自定义事件也是进一步有用。当然,事件也而不是囿于在四线程中,它能够用在单线程的前后相继中,作为一种对象间通信的体制。那么,为啥小编急需采纳事件,并不是实信号槽呢?主因是,事件的散发不只能够是同步的,又足以是异步的,而函数的调用大概说是槽的回调总是同步的。事件的别的四个益处是,它能够利用过滤器。

 

Qt
自定义事件极粗略,同任何类库的应用很相似,都是要持续二个类进行扩张。在
Qt 中,你须求后续的类是QEvent

继承QEvent类,最关键的是提供贰个QEvent::Type品类的参数,作为自定义事件的类型值。纪念一下,那么些type
是我们在处管事人件时用来识别事件类型的代号。举例在event()函数中,大家使用QEvent::type()得到这一个事件类型,然后与我们定义的实际上类型相比。

QEvent::TypeQEvent概念的贰个枚举。因而,大家能够传递三个int 值。不过急需留意的是,我们的自定义事件类型无法和已经存在的
type
值重复,不然会有不行预期的荒唐发生。因为系统会将你新增的平地风波作为系统事件进展派发和调用。在 Qt 中,系统保留 0 – 999
的值,约等于说,你的风浪 type 要大于 999。这种数值当然十分难记,所以 Qt
定义了七个边界值:QEvent::UserQEvent::MaxUser。大家的自定义事件的
type 应该在那五个值的界定里边。个中,QEvent::User的值是
1000,QEvent::MaxUser的值是 65535。从此处精晓,大家最多能够定义 64538个事件。通过那八个枚举值,大家得以确认保障大家协和的平地风波类型不会覆盖种类定义的轩然大波类型。不过,这样并不能够保证自定义事件互相之间不会被遮掩。为了消除这么些难点,Qt
提供了贰个函数:registerEventType(),用于自定义事件的登记。该函数签名如下:

 

 

 

1
static int QEvent::registerEventType ( int hint = -1 );

 

这些函数是 static 的,由此得以应用QEvent类直接调用。函数接受贰个 int
值,其暗中认可值是 -1;函数再次回到值是向系统登记的新的 Type 类型的值。倘使 hint
是合法的,也便是说那一个 hint
不会发出任何覆盖(系统的以及其它自定义事件的),则会一直回到这些值;否则,系统会自行分配一个合法值并再次来到。由此,使用那几个函数就可以成功
type 值的钦定。这一个函数是线程安全的,不必其他加上同步。

笔者们能够在QEvent子类中加多本人的风浪所必要的多寡,然后举办事件的发送。Qt
中提供了二种事件发送方式:

  1.  

     

    1
    2
    static bool QCoreApplication::sendEvent(QObject *receiver,
                                            QEvent *event);
直接将`event`事件发送给`receiver`接受者,使用的是`QCoreApplication::notify()`函数。函数返回值就是事件处理函数的返回值。在事件被发送的时候,`event`对象并不会被销毁。通常我们会在栈上创建`event`对象,例如:  
 

 

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-5a5958514604c422879003-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a5958514604c422879003-2">
2
</div>
</div></td>
<td><div class="crayon-pre">
<div id="crayon-5a5958514604c422879003-1" class="crayon-line">
QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
</div>
<div id="crayon-5a5958514604c422879003-2" class="crayon-line crayon-striped-line">
QApplication::sendEvent(mainWindow, &amp;event);
</div>
</div></td>
</tr>
</tbody>
</table>
  1.  

     

    1
    2
    static void QCoreApplication::postEvent(QObject *receiver,
                                            QEvent *event);
将`event`事件及其接受者`receiver`一同追加到事件队列中,函数立即返回。

 

因为 post 事件队列会持有事件对象,并且在其 post 的时候将其 delete
掉,因此,我们必须在堆上创建`event`对象。当对象被发送之后,再试图访问`event`对象就会出现问题(因为
post 之后,`event`对象就会被 delete)。

当控制权返回到主线程循环时,保存在事件队列中的所有事件都通过`notify()`函数发送出去。

事件会根据 post
的顺序进行处理。如果你想要改变事件的处理顺序,可以考虑为其指定一个优先级。默认的优先级是`Qt::NormalEventPriority`。

这个函数是线程安全的。

Qt 还提供了一个函数:

 

 

<table>
<colgroup>
<col style="width: 50%" />
<col style="width: 50%" />
</colgroup>
<tbody>
<tr class="odd">
<td><div class="crayon-nums-content">
<div class="crayon-num" data-line="crayon-5a59585146050200630279-1">
1
</div>
<div class="crayon-num crayon-striped-num" data-line="crayon-5a59585146050200630279-2">
2
</div>
</div></td>
<td><div class="crayon-pre">
<div id="crayon-5a59585146050200630279-1" class="crayon-line">
static void QCoreApplication::sendPostedEvents(QObject *receiver,
</div>
<div id="crayon-5a59585146050200630279-2" class="crayon-line crayon-striped-line">
                                               int event_type);
</div>
</div></td>
</tr>
</tbody>
</table>

这个函数的作用是,将事件队列中的接受者为`receiver`,事件类似为
event\_type 的所有事件立即发送给 receiver
进行处理。需要注意的是,来自窗口系统的事件并不由这个函数进行处理,而是`processEvent()`。详细信息请参考
Qt API 手册。

现行反革命,大家已经能够自定义事件指标,已经能够将事件发送出去,还剩下最后一步:管理自定义事件。管理自定义事件,同后面我们上课的那么些管理方法未有啥样差别。大家得以重写QObject::customEvent()函数,该函数接收贰个QEvent对象作为参数:

 

 

 

1
void QObject::customEvent(QEvent *event);

 

大家能够通过更动 event 对象类型来决断不一样的平地风波:

 

 

 

1
2
3
4
void CustomWidget::customEvent(QEvent *event) {
    CustomEvent *customEvent = static_cast<CustomEvent *>(event);
    // …
}

 

理当如此,我们也得以在event()函数中一贯管理:

 

 

 

1
2
3
4
5
6
7
8
bool CustomWidget::event(QEvent *event) {
    if (event->type() == MyCustomEventType) {
        CustomEvent *myEvent = static_cast<CustomEvent *>(event);
        // processing…
        return true;
    }
    return QWidget::event(event);
}

 

 

scutlpf  2014年2月19日 

”事件的分发既可以够是一起的,又足以是异步的,而函数的调用只怕说是槽的回调总是同步的。“那句话怎么通晓?

回复

  • 图片 1豆子
     2014年2月20日 

    协办就是调用者必需等到被调用者实践落成之后才具继续实施;异步就是被调用者在被调用之后立刻回到给调用者,调用者继续推行。函数调用和槽的进行都以共同的,就是要等到被调用的函数或槽实施达成,才回来给调用者继续实践,可以感到调用者被封堵了。对于事件,使用
    send伊芙nt 函数正是一同调用,使用 postEvent 正是异步调用。

 

博客转发自:

 Home

一、创设Qt gui应用对应的源码:

点击(此处)折叠或张开

  1. //mylineedit.h

  2. #ifndef MYLINEEDIT_H

  3. #define MYLINEEDIT_H
  4. #include <QWidget>
  5. #include <QLineEdit>
  6. class MyLineEdit : public QLineEdit
  7. {
  8. public:
  9.     explicit MyLineEdit(QWidget *parent = 0);
  10. protected:
  11.     void keyPressEvent(QKeyEvent
    *event);
  12. };
  13. #endif // MYLINEEDIT_H
  14. //mylineedit.cpp
  15. #include “mylineedit.h”
  16. #include <QLineEdit>
  17. #include <QDebug>
  18. #include <QKeyEvent>
  19. MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
  20. {
  21. }
  22. void MyLineEdit::keyPressEvent(QKeyEvent *event)
  23. {
  24.     qDebug() << QObject::tr(“MyLineEdit键盘按下事件”);
  25. }

那会儿只会产出“MyLineEidt键盘按下事件”。

Qt允许你创建和煦的事件类型,那在二十四线程的次序中国和越南社会主义共和国发有用,当然,也得以用在单线程的程序中,作为一种对象间通信的编写制定。那么,为何小编须求运用事件,而不是应用复信号槽呢?主因是,事件的分发不仅可以够是一只的,又能够是异步的,而函数的调用可能说是槽的回调总是同步的。事件的别的三个功利是,它能够运用过滤器。

尽管 Qt
已经提供了非常多事件,但对于更为波谲云诡的须要来讲,有限的事件都以远远不够的。例如,作者要扶助一种新的设备,那一个装置提供一种全新的交互形式,那么,这种事件怎么着管理呢?所以,允许成立本身的风浪类型也就从事情发展的趋势看必得采取行动。即就是不说这种不行极端的例证,在二十八线程的顺序中,自定义事件也是更进一步有用。当然,事件也并不是受制在八线程中,它能够用在单线程的主次中,作为一种对象间通信的编写制定。那么,为何自个儿索要利用事件,而不是时限信号槽呢?主因是,事件的散发既可以够是一块的,又能够是异步的,而函数的调用也许说是槽的回调总是同步的。事件的别的四个收益是,它可以采用过滤器。

 / 

二、第二次修改

在mylineedit.cpp中keyPressEvent()添加

  1. event->ignore();
    //忽略该事件

结果:多产出了”Widget键盘按下事件”,而且lineedit不能输入了。

Qt中的自定义事件非常的粗略,同任何类似的库的应用很相似,都是要三番五次二个类举办扩充。在Qt中,你需求后续的类是Q伊夫nt。注意,在Qt3中,你须求继续的类是QCustomEvent,不过这些类在Qt4中一度被丢弃(这里的甩掉是不提议接纳,并不是从类库中剔除)。

Qt
自定义事件很简短,同别的类库的运用很一般,都是要三番两次一个类实行扩张。在
Qt 中,你须求后续的类是QEvent

Qt 学习之路 2

三、第一次修改

在mylineedit.h中添加public函数:

  1. bool event(QEvent *event);

下一场定义:

  1. bool MyLineEdit::event(QEvent *event)

  2. {

  3.     if(event->type()
    == QEvent::KeyPress)
  4.         qDebug()<<QObject::tr(“MylineEdit的event()函数”);
  5.     return QLineEdit::event(event);
  6. }

再三再四QEvent类,你必要提供二个QEvent::Type类型的参数,作为自定义事件的类型值。这里的Q伊夫nt::Type类型是QEvent里面定义的七个enum,由此,你是足以传递叁个int的。首要的是,你的风云类型不能够和早就存在的type值重复,不然会有不足预料的谬误发生!因为系统会将你的风云视作系统事件进展派发和调用。在Qt中,系统将保留0

继承QEvent类,最关键的是提供多个QEvent::Type项目标参数,作为自定义事件的类型值。回忆一下,这一个type
是大家在处总管件时用来识别事件类型的代号。例如在event()函数中,大家利用QEvent::type()获取那几个事件类型,然后与大家定义的莫过于类型相比。

 / 

四、第伍回修改

widget.h中public申明:

  1. bool eventFilter(QObject *obj,QEvent *event);

widget.cpp构造函数扩展代码,并扩张事件过滤器函数的定义:

  1. line艾德it->installEventFilter(this);
    //在widget上为lineEdit安装事件过滤器

  2. bool Widget::eventFilter(QObject *watched, QEvent *event)

  3. {
  4.     if(watched==lineEdit) {
  5.         if(event->type()==QEvent::KeyPress)
  6.             qDebug()<<QObject::tr(“Widget的平地风波过滤器”);
  7.     }
  8.     return QWidget::eventFilter(watched, event);
  9. }

图片 2
五、最后的源码:
mylineedit:

  1. //mylineedit.h

  2. #ifndef MYLINEEDIT_H

  3. #define MYLINEEDIT_H
  4. #include <QWidget>
  5. #include <QLineEdit>
  6. class MyLineEdit : public QLineEdit
  7. {
  8. public:
  9.     explicit MyLineEdit(QWidget *parent = 0);
  10.     bool event(QEvent *event);
  11. protected:
  12.     void keyPressEvent(QKeyEvent
    *event);
  13. };
  14. #endif // MYLINEEDIT_H
  15. //mylineedit.cpp
  16. #include “mylineedit.h”
  17. #include <QLineEdit>
  18. #include <QDebug>
  19. #include <QKeyEvent>
  20. MyLineEdit::MyLineEdit(QWidget *parent):QLineEdit(parent)
  21. {
  22. }
  23. bool MyLineEdit::event(QEvent *event)
  24. {
  25.     if(event->type()
    == QEvent::KeyPress)
  26.         qDebug()<<QObject::tr(“MylineEdit的event()函数”);
  27.     return QLineEdit::event(event);
  28. }
  29. void MyLineEdit::keyPressEvent(QKeyEvent *event)
  30. {
  31.     qDebug() << QObject::tr(“MyLineEdit键盘按下事件”);
  32.     QLineEdit::keyPressEvent(event);
  33.     event->ignore();
  34. }

midget:

  1. //wdiget.h

  2. #ifndef WIDGET_H

  3. #define WIDGET_H
  4. #include <QWidget>
  5. class MyLineEdit;
  6. namespace Ui {
  7. class Widget;
  8. }
  9. class Widget : public QWidget
  10. {
  11.     Q_OBJECT
  12. public:
  13.     explicit Widget(QWidget
    *parent = 0);
  14.     ~Widget();
  15.     bool eventFilter(QObject
    *watched, QEvent *event);
  16. protected:
  17.     void keyPressEvent(QKeyEvent
    *event);
  18. private:
  19.     Ui::Widget *ui;
  20.     MyLineEdit *lineEdit;
  21. };
  22. #endif // WIDGET_H
  23. //widget.cpp
  24. #include “widget.h”
  25. #include “ui_widget.h”
  26. #include “mylineedit.h”
  27. #include <QKeyEvent>
  28. #include <QDebug>
  29. Widget::Widget(QWidget *parent) :
  30.     QWidget(parent),
  31.     ui(new Ui::Widget)
  32. {
  33.     lineEdit = new
    MyLineEdit(this);
  34.     lineEdit->move(100, 100);
  35.     line艾德it->installEventFilter(this);
    //在widget上为lineEdit安装事件过滤器
  36.     ui->setupUi(this);
  37. }
  38. Widget::~Widget()
  39. {
  40.     delete ui;
  41. }
  42. bool Widget::eventFilter(QObject *watched, QEvent *event)
  43. {
  44.     if(watched==lineEdit) {
  45.         if(event->type()==QEvent::KeyPress)
  46.             qDebug()<<QObject::tr(“Widget的事件过滤器”);
  47.     }
  48.     return QWidget::eventFilter(watched, event);
  49. }
  50. void Widget::keyPressEvent(QKeyEvent *event)
  51. {
  52.     qDebug()<<QObject::tr(“Widget键盘按下事件”);
  53. }
  • 999的值,也便是说,你的事件type要当先999.
    具体来讲,你的自定义事件的type要在Q伊芙nt::User和Q伊夫nt::马克斯User的限定之间。在那之中,Q伊夫nt::User值是一千,QEvent::马克斯User的值是65535。从那边了然,你最多能够定义64538个事件,相信这一个数字已经足足大了!然则,固然如此,也只能保险客商自定义事件不可能遮蔽种类事件,并无法确定保障自定义事件时期不会被覆盖。为了减轻这些主题材料,Qt提供了三个函数:register伊芙ntType(),用于自定义事件的注册。该函数具名如下:

QEvent::TypeQEvent概念的一个枚举。由此,大家得以传递叁个 int
值。不过要求小心的是,大家的自定义事件类型不可能和已经存在的 type
值重复,否则会有不行预料的荒唐爆发。因为系统会将您新增的平地风波视作系统事件开展派发和调用。在
Qt 中,系统一保险留 0 – 999 的值,也正是说,你的平地风波 type 要超越999。这种数值当然特别难记,所以 Qt
定义了七个边界值:QEvent::UserQEvent::MaxUser。大家的自定义事件的
type 应该在这四个值的限定以内。其中,QEvent::User的值是
1000,QEvent::MaxUser的值是 65535。从这里了然,大家最多能够定义 64538个事件。通过那五个枚举值,大家能够保险咱们和谐的平地风波类型不会覆盖种类定义的平地风波类型。不过,那样并不可能保障自定义事件相互之间不会被遮掩。为了消除那几个标题,Qt
提供了二个函数:registerEventType(),用于自定义事件的登记。该函数具名如下:

Qt 学习之路 2(18):事件

图片 3static int QEvent::registerEventType
( int hint = -1 );
函数是static的,因而得以利用QEvent类直接调用。函数接受三个int值,其暗许值为-1,重回值是开创的那个Type类型的值。假如hint是官方的,不会发出其余覆盖,则会回来那么些值;倘若hint违规,系统会活动分配贰个法定值并回到。因而,使用那些函数就可以形成type值的内定。那一个函数是线程安全的,由此不用其他增添同步。

static int QEvent::registerEventType ( int hint = -1 );

Qt 学习之路 2(18):事件

 豆子  2012年9月27日  Qt 学习之路
2  60条评论

事件(event)是由系统或然 Qt
自个儿在差异的每日发生的。当客商按下鼠标、敲下键盘,只怕是窗口须要再一次绘制的时候,都会发出叁个相应的风云。一些事变在对客户操作做出响应时发出,如键盘事件等;另一部分风浪则是由系统活动发出,如沙漏事件。

 

事件也正是我们平常说的“事件驱动(event
drive)”程序设计的底子概念。事件的产出,使得程序代码不会遵纪守法原有的线性顺序试行。想想看,从开始时期的
C
语言开端,大家的次第正是以一种线性的各种实施代码:这一条语句实践之后,早先实践下一条语句;那贰个函数实施过后,初步执行下一个函数。这种接近“批处理”的主次设计风格显明不符合于管理复杂的客户交互。我们来设想一下客商交互的情景:大家陈设了一群效果放在分界面上,顾客点击了“展开文件”,于是从头试行张开文件的操作;顾客点击了“保存文件”,于是从头实施保存文件的操作。大家不清楚客户到底想实行怎么着操作,由此也就不能够预测接下去将会调用哪贰个函数。假设大家统筹了一个“文件另存为”的操作,假如客商不点击,这么些操作将永恒不会被调用。那就是所谓的“事件驱动”,大家的主次的实施各类不再是线性的,而是由二个个事件驱动着程序继续施行。未有事件,程序将封堵在那边,不实践别的轮代理公司码。

在 Qt 中,事件的定义如同同能量信号槽类似。的确如此,一般的话,使用 Qt
组件时,我们并不会把主要精力放在事件上。因为在 Qt
中,大家关心的愈来愈多的是事件涉及的一个非能量信号。举个例子,对于QPushButton的鼠标点击,大家无需关切这几个鼠标点击事件,而是关注它的clicked()实信号的爆发。那与别的的片段
GUI 框架不一样:在 Swing
中,你所要关切的是JButtonActionListener那个点击事件。由此看出,比较于其他GUI 框架,Qt 给了我们非常的选项:复信号槽。

而是,Qt
中的事件和时限信号槽却并非可以相互取代的。时限信号由具体的对象发出,然后会立马交给由connect()函数连接的槽实行管理;而对此事件,Qt
使用七个事件队列对富有爆发的事件进行保障,当新的风浪发生时,会被追加到事件队列的尾巴。前三个风浪变成后,抽取前边的事件张开管理。可是,须求的时候,Qt
的风浪也得以不进来事件队列,而是一贯管理。随机信号一旦发生,对应的槽函数一定会被实行。不过,事件则能够采纳“事件过滤器”进行过滤,对于某件事件实行额外的拍卖,别的的轩然大波则不关心。总的来讲,假如大家使用组件,大家关怀的是复信号槽;假若大家自定义组件,我们关心的是事件。因为大家能够透过事件来改变组件的暗中认可操作。比如,借使我们要自定义三个可见响应鼠标事件的EventLabel,我们就须要重写QLabel的鼠标事件,做出大家期望的操作,有希望还得在适用的时候发出贰个临近开关的clicked()非数字信号(若是大家希望让那一个EventLabel能够被别的组件使用)可能别的的实信号。

在前方大家也早就轻便关联,Qt
程序供给在main()函数创制多个QCoreApplication目的,然后调用它的exec()函数。这么些函数正是初阶Qt
的事件循环。在实践exec()函数之后,程序将进入事件循环来监听应用程序的平地风波。当事件时有爆发时,Qt
将创造二个事件目的。Qt
中全体事件类都一连于QEvent。在事件指标创制完结后,Qt
将以那一件事件指标传递给QObjectevent()函数。event()函数并不直接处监护人件,而是遵循事件指标的品种分派给一定的事件管理函数(event
handler)。关于那一点,大家会在其后的章节中详尽表明。

在具备组件的父类QWidget中,定义了好些个事件管理的回调函数,如keyPressEvent()keyReleaseEvent()mouseDoubleClickEvent()mouseMoveEvent()mousePressEvent()mouseReleaseEvent()等。这么些函数都以protected virtual
的,也等于说,大家能够在子类中再次完成那几个函数。上面来看贰个事例:

 

 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
class EventLabel : public QLabel
{
protected:
    void mouseMoveEvent(QMouseEvent *event);
    void mousePressEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);
};
 
void EventLabel::mouseMoveEvent(QMouseEvent *event)
{
    this->setText(QString("<center><h1>Move: (%1, %2)</h1></center>")
                  .arg(QString::number(event->x()), QString::number(event->y())));
}
 
void EventLabel::mousePressEvent(QMouseEvent *event)
{
    this->setText(QString("<center><h1>Press: (%1, %2)</h1></center>")
                  .arg(QString::number(event->x()), QString::number(event->y())));
}
 
void EventLabel::mouseReleaseEvent(QMouseEvent *event)
{
    QString msg;
    msg.sprintf("<center><h1>Release: (%d, %d)</h1></center>",
                event->x(), event->y());
    this->setText(msg);
}
 
int main(int argc, char *argv[])
{
    QApplication a(argc, argv);
 
    EventLabel *label = new EventLabel;
    label->setWindowTitle("MouseEvent Demo");
    label->resize(300, 200);
    label->show();
 
    return a.exec();
}

大家编写翻译运维方面包车型客车代码,就足以知晓到有关事件的利用格局。

EventLabel继承了QLabel,覆盖了mousePressEvent()mouseMoveEvent()MouseReleaseEvent()四个函数。我们并未增进什么功用,只是在鼠标按下(press)、鼠标移动(move)和鼠标释放(release)的时候,把当下鼠标的坐标值展现在那么些Label上面。由于QLabel是永葆
HTML 代码的,由此大家直接使用了 HTML 代码来格式化文字。

QStringarg()函数能够自动替换掉QString中冒出的占位符。其占位符以
% 初阶,前面是占位符的岗位,比方 %1,%2 这种。

 

 

1
QString("[%1, %2]").arg(x, y);

言语将会利用 x 替换 %1,y 替换 %2,由此,那些讲话生成的QString为 [x,
y]。

mouseReleaseEvent()函数中,大家应用了别的一种QString的构造方法。大家运用类似
C 风格的格式化函数sprintf()来构造QString

运营方面包车型客车代码,当我们点击了一晃鼠标之后,label 上将展现鼠标当前坐标值。

图片 4

缘何要点击鼠标之后才具在mouseMoveEvent()函数中显得鼠标坐标值?这是因为QWidget中有三个mouseTracking品质,该属性用于安装是不是追踪鼠标。独有鼠标被追踪时,mouseMoveEvent()才会生出。纵然mouseTracking
false(默许正是),组件在至少叁遍鼠标点击之后,才具够被追踪,也正是能力所能达到产生mouseMoveEvent()事件。如果mouseTracking
true,则mouseMoveEvent()从来能够被发生。知道了这点,大家就足以在main()函数中一向设置下:

 

 

1
2
3
4
5
EventLabel *label = new EventLabel;
label->setWindowTitle("MouseEvent Demo");
label->resize(300, 200);
label->setMouseTracking(true);
label->show();

那样子就从未这些标题了。

你能够在Q伊芙nt子类中增添自个儿的风浪所急需的多少,然后举办事件的发送。Qt中提供了二种发送形式:

其一函数是 static 的,由此能够利用QEvent类直接调用。函数接受叁个 int
值,其私下认可值是 -1;函数重回值是向系统注册的新的 Type 类型的值。假诺 hint
是官方的,也正是说那几个 hint
不会时有产生任何覆盖(系统的以及任何自定义事件的),则会直接重临这么些值;不然,系统会自行分配三个合法值并重临。由此,使用那一个函数就可以形成type 值的钦定。这几个函数是线程安全的,不必别的加上同步。

  • static bool QCoreApplication::sendEvent(QObjecy * receiver,
    QEvent *
    event):事件被QCoreApplication的notify()函数直接发送给receiver对象,再次来到值是事件处理函数的重回值。使用那些函数要求求在栈上创制对象,比方:
    图片 5QMouseEvent
    event(QEvent::MouseButtonPress, pos, 0, 0, 0);
    图片 6QApplication::sendEvent(mainWindow,
    &event);
  • static bool QCoreApplication::postEvent(QObject * receiver,
    QEvent *
    event):事件被QCoreApplication追加到事件列表的最后,并等候管理,该函数将事件追加后会马上赶回,并且注意,该函数是线程安全的。其余一些是,使用那么些函数必须要在堆上创建对象,例如:
    图片 7QApplication::post伊夫nt(object,
    new
    My伊芙nt(QEvent::register伊夫ntType(2048)));那几个指标无需手动delete,Qt会自行delete掉!因而,借使在post事件之后调用delete,程序恐怕会崩溃。其余,postEvent()函数还只怕有三个重载的版本,增添八个开始的一段时期级参数,具体请参见API。通过调用sendPostedEvent()函数能够让已提交的事件及时得到管理。

大家得以在QEvent子类中增多自个儿的平地风波所须求的数额,然后开展事件的出殡。Qt
中提供了二种事件发送格局:

假设要管理自定义事件,能够重写QObject的customEvent()函数,该函数接收四个Q伊芙nt对象作为参数。注意,在Qt3中这一个参数是QCustomEvent类型的。你能够像前边介绍的重写event()函数的艺术去重写那些函数:

方式一:

图片 8void CustomWidget::customEvent(QEvent
*event) {
图片 9        CustomEvent *customEvent =
static_cast<CustomEvent *>(event);
图片 10        // ….
图片 11}
除此以外,你也足以因而重写event()函数来拍卖自定义事件:

static bool QCoreApplication::sendEvent(QObject *receiver,
                                        QEvent *event);

图片 12bool CustomWidget::event(QEvent
*event) {
图片 13        if (event->type() ==
MyCustomEventType) {
图片 14                CustomEvent *myEvent
= static_cast<CustomEvent *>(event);
图片 15                // processing…
图片 16                return true;
图片 17        }
图片 18
        return QWidget::event(event);
图片 19}
那三种艺术都以行得通的。

直接将event事件发送给receiver接受者,使用的是QCoreApplication::notify()函数。函数再次来到值正是事件管理函数的再次回到值。在事变被发送的时候,event目的并不会被灭绝。平常大家会在栈上创造event对象,例如:

好了,至此,我们已经轮廓的牵线了Qt的平地风波机制,包涵事件的派发、自定义等一文山会海的主题材料。上边包车型客车章节将继续大家的学习之路!

QMouseEvent event(QEvent::MouseButtonPress, pos, 0, 0, 0);
QApplication::sendEvent(mainWindow, &event);

本文出自 “豆子空间”
博客,请必须保留此出处

方式二:

Qt允许你创设自个儿的平地风波类…

static void QCoreApplication::postEvent(QObject *receiver,
                                        QEvent *event);

event事件及其接受者receiver一路追加到事件队列中,函数马上赶回。

 

因为 post 事件队列会怀有事件目的,并且在其 post 的时候将其 delete
掉,因而,大家无法不在堆上创造event目的。当指标被发送之后,再试图访谈event对象就可以冒出难点(因为
post 之后,event对象就能够被 delete)。

当调整权再次回到到主线程循环时,保存在事件队列中的全部事件都经过notify()函数发送出去。

事件会遵照 post
的逐个举办管理。假诺你想要改动事件的拍卖顺序,能够思虑为其钦定贰个优先级。默许的预先级是Qt::NormalEventPriority

这一个函数是线程安全的。

Qt 还提供了三个函数:

static void QCoreApplication::sendPostedEvents(QObject *receiver,
                                               int event_type);
  1. 那几个函数的效果是,将事件队列中的接受者为receiver,事件类似为
    event_type 的具有事件登时发送给 receiver
    举办拍卖。供给静心的是,来自窗口系统的风云并不由这几个函数进行拍卖,而是processEvent()。详细新闻请参见
    Qt API 手册。

当今,大家早已能够自定义事件目的,已经能够将事件发送出去,还剩余最后一步:管理自定义事件。管理自定义事件,同前边大家讲课的那个管理措施未有何分别。大家得以重写QObject::customEvent()函数,该函数接收二个QEvent目的作为参数:

void QObject::customEvent(QEvent *event);

笔者们可以透过退换 event 对象类型来判断分化的事件:

void CustomWidget::customEvent(QEvent *event) {
    CustomEvent *customEvent = static_cast<CustomEvent *>(event);
    // ...
}

自然,大家也足以在event()函数中一向管理:

bool CustomWidget::event(QEvent *event) {
    if (event->type() == MyCustomEventType) {
        CustomEvent *myEvent = static_cast<CustomEvent *>(event);
        // processing...
        return true;
    }
    return QWidget::event(event);
}

 

相关文章