53 QT事件系统

QEvent有什么用?

QEvent 类是所有事件类的基类,事件对象包含事件参数。

Qt 的主事件循环(QCoreApplication::exec())从事件队列中获取本地窗口系统事件,将它们转化为 QEvents,然后将转换后的事件发送给 QObjects。

在Qt中,事件作为一个对象,继承自QEvent类,常见的有键盘事件QKeyEvent、鼠标事件QMouseEvent和定时器事件QTimerEvent等,它们与QEvent类的继承关系如图所示。

Qt中的事件是什么?有什么用?

事件是对各种应用程序需要知道的由应用程序内部或者外部产生的事情或者动作的通称。在Qt中使用一个对象来表示一个事件,它继承自QEvent类。  

事件与信号并不相同,比如我们使用鼠标点击了一下界面上的按钮,那么就会产生鼠标事件QMouseEvent(不是按钮产生的),而因为按钮被按下了,所以它会发出clicked()单击信号(是按钮产生的)。这里一般只关心按钮的单击信号,而不用考虑鼠标事件,但是如果要设计一个按钮,或者当鼠标点击按钮时让它产生别的效果,那么就要关心鼠标事件了。可以看到,事件与信号是两个不同层面的东西,它们的发出者不同,作用也不同。在Qt中,任何QObject的子类的实例都可以接收和处理事件。  

常见事件:鼠标事件、键盘事件、定时事件、上下文菜单事件、关闭事件、拖放事件、绘制事件等。

Qt中的事件如何处理?

方法一:重新实现部件的paintEvent(),mousePressEvent()等事件处理函数。这是最常用也的一种方法,不过它只能用来处理特定部件的特定事件。例如拖放操作,就是用的这种方法。

方法二:重新实现notify()函数。这个函数功能强大,提供了完全的控制,可以在事件过滤器得到事件之前就获得它们。但是,它一次只能处理一个事件。

方法三:向QApplication对象上安装事件过滤器。因为一个程序只有一个QApplication对象,所以这样实现的功能与使用notify()函数是相同的,优点是可以同时处理多个事件。

方法四:重新实现event()函数。QObject类的event()函数可以在事件到达默认的事件处理函数之前获得该事件。

方法五:在对象上安装事件过滤器。使用事件过滤器可以在一个界面类中同时处理不同子部件的不同事件。

在实际编程中,最常用的是方法一,其次是方法五。

1.重新实现事件处理函数

Skills:

如果你想重新实现事件处理函数,可以先到QWidget中的找到相应的函数,然后把整个函数的定义复制到你要实现的地方。

 

例如:使用自定义的Widget作为主窗口(继承自QWidget),然后在上   面放置一个自定义的MyLineEdit(继承自QLineEdit)。

在MyLineEdit中添加键盘按下事件处理函数声明:

protected:
    void keyPressEvent(QKeyEvent *event);

事件处理函数的定义:

void MyLineEdit::keyPressEvent(QKeyEvent *event)    // 键盘按下事件
{
    qDebug() << tr("MyLineEdit键盘按下事件");
    QLineEdit::keyPressEvent(event);   // 执行QLineEdit类的默认事件处理
    event->ignore();                          // 忽略该事件
}

在Widget中添加键盘按下事件处理函数声明:

protected:
    void keyPressEvent(QKeyEvent *event);

widget的构造函数:

Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
    lineEdit = new MyLineEdit(this);
    lineEdit->move(100, 100);
}

事件处理函数的定义:

void Widget::keyPressEvent(QKeyEvent *event)
{
    qDebug() << tr("Widget键盘按下事件");
}

从这个例子中可以看到,事件是先传递给指定窗口部件的,这里确切的说应该是先传递给获得焦点的窗口部件的。但是如果该部件忽略掉该事件,那么这个事件就会传递给这个部件的父部件。在重新实现事件处理函数时,一般要调用父类的相应的事件处理函数来实现默认的操作。

2.安装事件过滤器

在MyLineEdit中添加函数声明:

bool event(QEvent *event);

//该函数定义:
bool MyLineEdit::event(QEvent *event)  // 事件
{
    if(event->type() == QEvent::KeyPress)
        qDebug() << tr("MyLineEdit的event()函数");
    return QLineEdit::event(event);  //执行QLineEdit类event()函数的默认操作
}

在MyLineEdit的event()函数中使用了QEvent的type()函数来获取事件的类型,如果是键盘按下事件QEvent::KeyPress,则输出信息。因为event()函数具有bool型的返回值,所以在该函数的最后要使用return语句,这里一般是返回父类的event()函数的操作结果。

在Widget中进行事件过滤器函数的声明:

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

在widget.cpp文件中的构造函数的最后添上一行代码:

lineEdit->installEventFilter(this);   // 在Widget上为lineEdit安装事件过滤器

下面是事件过滤器函数的定义:

bool Widget::eventFilter(QObject *obj, QEvent *event) // 事件过滤器
{   
          if(obj == lineEdit) {              // 如果是lineEdit部件上的事件        
                    if(event->type() == QEvent::KeyPress)            
                    qDebug() << tr("Widget的事件过滤器");    
           }    
         return QWidget::eventFilter(obj, event);
} 

在事件过滤器中,先判断该事件的对象是不是lineEdit,如果是,再判断事件类型。最后返回了QWidget类默认的事件过滤器的执行结果。

事件的传递

在每个程序的main()函数的最后,都会调用QApplication类的exec()函数,它会使Qt应用程序进入事件循环,这样就可以使应用程序在运行时接收发生的各种事件。一旦有事件发生,Qt便会构建一个相应的QEvent子类的对象来表示它,然后将它传递给相应的QObject对象或其子对象。    

 从前面的例子可以看到,事件的传递顺序是这样的:先是事件过滤器,然后是该部件的event()函数,最后是该部件的事件处理函数。这里还要注意,event()函数和事件处理函数,是在该部件内进行重新定义的,而事件过滤器却是在该部件的父部件中进行定义的。

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值