QT编程----事件(一)

review

.ui生成.h.cpp文件

uicform1.ui-oform1.h

uicform1.ui-iform1.h-oform1.cpp

C++三个特点:继承重载封装

QT程序设计进阶-事件

Qt事件

Qt程序是事件驱动的,程序的每个动作都是由幕后某个事件所触发.

Qt事件的类型很多,常见的qt的事件如下:
键盘事件:按键按下和松开.
鼠标事件:鼠标移动,鼠标按键的按下和松开.
拖放事件:用鼠标进行拖放.
滚轮事件:鼠标滚轮滚动.
绘屏事件:重绘屏幕的某些部分.
定时事件:定时器到时.
焦点事件:键盘焦点移动.
进入和离开事件:鼠标移入widget之内,或是移出.
移动事件:widget的位置改变.
大小改变事件:widget的大小改变.
显示和隐藏事件:widget显示和隐藏.
窗口事件:窗口是否为当前窗口.

还有一些非常见的qt事件,比如socket事件,剪贴板事件,字体改变,布局改变等等.

Qt的事件和Qt中的signal不一样.后者通常用来使用widget,而前者用来实现widget.

比如一个按钮,我们使用这个按钮的时候,我们只关心他clicked()signal,至于这个按钮如何接收处理鼠标事件,再发射这个信号,我们是不用关心的.但是如果我们要重载一个按钮的时候,我们就要面对event.比如我们可以改变它的行为,在鼠标按键按下的时候(mousepressevent)就触发clicked()signal而不是通常在释放的(mousereleaseevent)时候.

事件起源:

基于事件如何被产生与分发,可以把事件分为三类:

1)Spontaneous事件

2)Posted事件

3)Sent事件

1)Spontaneous事件,由窗口系统产生,它们被放到系统队列中,通过事件循环逐个处理。

本类事件通常是windowsystem把从系统得到的消息,比如鼠标按键,键盘按键等,放入系统的消息队列中.Qt事件循环的时候读取这些事件,转化为QEvent,再依次处理.

2)Posted事件,由Qt或是应用程序产生,它们被Qt组成队列,再通过事件循环处理。

调用QApplication::postEvent()来产生一个posted类型事件.

例如:QWidget::update()函数

当需要重新绘制屏幕时,程序调用update()函数

其实现的原理是new出一个paintEvent,调用QApplication::postEvent(),将其放入Qt的消息队列中,等待依次被处理.

3)Sent事件由Qt或是应用程序产生,但它们被直接发送到目标对象。

调用QApplication::sendEvent()函数来产生一个sent类型事件.

sent类型事件不会放入队列,而是直接被派发和处理,QWidget::repaint()函数用的就是这种方式.

当我们在main()函数的末尾调用QApplication::exec(),程序进入了Qt的事件循环

事件循环如下面所示:

while(!exit_was_called)

{

while(!posted_event_queue_is_empty)

{

process_next_posted_event();

}

while(!spontaneous_event_queue_is_empty)

{

process_next_spontaneous_event();

}

while(!posted_event_queue_is_empty)

{

process_next_posted_event();

}

}

事件循环的处理流程:

1)先处理Qt事件队列中的posted事件,直至为空

2)再处理系统消息队列中的spontaneous消息,直至为空

3)在处理系统消息的时候会产生新的Qtposted事件,需要对其再次进行处理

不通过事件循环

sendEvent的事件派发不通过事件循环。QApplication::sendEvent()是通过调用QApplication::notify(),直接进入了事件的派发和处理环节。

Notify

调用QApplication::sendEvent的时候,消息会立即被处理,是同步的.实际上QApplication::sendEvent()是通过调用QApplication::notify(),直接进入了事件的派发和处理环节.所有的事件都最终通过notify派发到相应的对象中。

boolQApplication::notify(QObject*receiver,QEvent*event)

它是通过调用receiver->event(event)来实现的。

目标接受对象的event方法会自动接受notify传来的event事件

event()会返回一个布尔值,来告诉调用者是否事件被acceptignore,

(true表示accept),从event()返回的布尔值却是用来与QApplication:notify()通讯的

event()函数的处理如下所示:

boolQWidget::event(QEvent*event)

{

switch(e->type()){

caseQEvent::KeyPress:

keyPressEvent((QKeyEvent*)event);

if(!((QKeyEvent*)event)->isAccepted())

returnfalse;

break;

caseQEvent::KeyRelease:

keyReleaseEvent((QKeyEvent*)event);

if(!((QKeyEvent*)event)->isAccepted())

returnfalse;

break;

...

}

returntrue;

}

Close事件有点不同,调用QCloseEvent:ignore()取消了关闭操作,而accept()告诉Qt继续执行正常的关闭操作。为了避免混乱,最好是在closeEvent()的新实现中明确地进行accept()ignore()的调用:、

voidMainWindow::closeEvent(QCloseEvent*event)

{

if(userReallyWantsToQuit()){

event->accept();

}else{

event->ignore();

}

}

例子:keyPressEvent

在空白窗体页面,重载当前窗体类的keyPressEvent方法,实现按键事件的响应。

步骤一:

添加头文件<qevent.h>

form.cpp中填加voidForm1::keyPressEventQKeyEvent*k

并实现根据不同的键值,执行不同的动作。

步骤二:

添加头文件<qevent.h>

form.h中为窗体类form1添加voidkeyPressEventQKeyEvent*k)声明;

步骤三:

重新编译工程并运行测试。

voidForm1::keyPressEvent(QKeyEvent*k)

{

if(k->key()==Key_Left)

{

qDebug("Left\n");

....

}

elseif(k->key()==Key_Right)

{

qDebug("Right\n");

...

}

elseQWidget::keyPressEvent(k);

}

在具备子控件的复杂窗体中,重载当前窗体类的keyPressEvent方法,实现按键事件的响应。

步骤一:

添加头文件<qevent.h>

form.cpp中填加voidForm1::keyPressEventQKeyEvent*k

并实现根据不同的键值,执行不同的动作。

步骤二:

添加头文件<qevent.h>

form.h中为窗体类form1添加voidkeyPressEventQKeyEvent*k)声明;

步骤三:

form.cpp中,消除子控件的焦点策略,使能方向及Tab按键功能。

步骤四:

重新编译工程并运行测试。

例如:

pushButton1=newQPushButton(this,"pushButton1");

pushButton1->setGeometry(QRect(200,150,111,41));

pushButton1->setFocusPolicy(QWidget::NoFocus);

voidQWidget::setFocusPolicy(FocusPolicy)

设置这个窗口部件接收键盘焦点的方式。

“focusPolicy”属性保存的是窗口部件接收键盘焦点的策略。

如果窗口部件通过tab来接收键盘焦点,这个策略就是QWidget::TabFocus

如果窗口部件通过点击来接收键盘焦点,这个策略就是QWidget::ClickFocus

如果窗口部件上述两种方式都使用,是QWidget::StrongFocus

如果它不接收焦点(QWidget的默认值),是QWidget::NoFocus

重载当前窗体类的event方法,实现针对性事件的处理与过滤效果。

步骤一:

form.cpp中填加boolForm1::eventQEvent*event

并实现根据不同的键值,执行不同的动作。

步骤二:

form.h中为窗体类form1添加booleventQEvent*event)声明;

步骤三:

重新编译工程并运行测试。

boolForm1::event(QEvent*event)

{

if(event->type()==QEvent::KeyPress)

{

QKeyEvent*keyEvent=(QKeyEvent*)event;

if(keyEvent->key()==Key_A)

{

qDebug("--cuttheKey_A--\n");

returntrue;

}

}

returnQWidget::event(event);

}

实验:

1)用鼠标事件实现鼠标放在按钮上,按钮变大。

2)用按键事件实现方向右和方向左键控制2个窗口

3)用信号与槽机制实现鼠标点击nextback实现控制2个窗口

main.cpp:


form1.cpp


form2.cpp


QT编程----事件(一) QT编程----事件(一)

你可能感兴趣的:(编程)