[Qt][Qt 事件][下]详细讲解


1.定时器

0.是什么?

  • 在进⾏窗⼝程序的处理过程中,经常要周期性的执⾏某些操作,或者制作⼀些动画效果,使⽤定时器就可以实现
  • 定时器:就是在间隔⼀定时间后,去执⾏某⼀个任务
  • Qt中的定时器分为QTimerEventQTimer这2个类

1.QTimerEvent

  • QTimerEvent:⽤来描述⼀个定时器事件
  • 使用
    • startTimer():开启⼀个定时器
      • 参数:以毫秒为单位的整数作为参数来表明设定的时间
      • 返回值:一个整形的身份标识,代表这个定时器
    • 当定时器溢出时(即定时时间到达)就可以在timerEvent()中获取该定时器的编号来进⾏相关操作
    • killTimer:关闭定时器
  • 注意:如果一个程序中存在多个定时器(startTimer创建的定时器),此时每个定时器都会触发timerEvent()
  • 示例
    // 构造函数中
    {
    	// 开启定时器事件.
    	// 此处 timerId 是一个定时器的身份标识.
    	timerId = this->startTimer(1000);
    }
    
    void Widget::timerEvent(QTimerEvent* event)
    {
    	// 先判定一下这次触发是否是想要的定时器触发的.
    	if (event->timerId() != this->timerId) 
    	{
    		return;
    	}
    	
    	int value = ui->lcdNumber->intValue();
    	if (value <= 0) 
    	{
    		// 停止定时器
    		this->killTimer(this->timerId);
    		return;
    	}
    	
    	value -= 1;
    	ui->lcdNumber->display(value);
    }
    

2.QTimer

  • QTimer底层是QTimerEvent
  • QTimer实现⼀个定时器,它提供了更⾼层次的编程接⼝
    • 如:可以使⽤信号和槽,还可以设置只运⾏⼀次的定时器
  • 示例
    QTimer* timer = new QTimer(this);
    
    connect(ui->btn1, &QPushButton::clicked, [=](){
    	timer->start(1000);
    });
    
    connect(timer, &QTimer::timeout, [=](){
    	static int num = 1;
    	ui->label->setText(QString::number(num++));
    });
    
    connect(ui->btn2, &QPushButton::clicked, [=](){
    	timer->stop();
    });
    

3.获取系统⽇期及时间

  • 在Qt中,获取系统的⽇期及实时时间可以通过QTimer类和QDateTime

  • QDateTime类提供了字符串格式的时间,输出格式由toString()⽅法中的format参数列表决定

    请添加图片描述

  • 示例

    // 构造函数中
    {
    	QTimer* timer = new QTimer(this);
    
    	connect(ui->btn1, &QPushButton::clicked, [=](){
    		timer->start(1000);
    	});
    
    
    	connect(ui->btn2, &QPushButton::clicked, [=](){
    		timer->stop();
    	});
    
    	connect(timer, &QTimer::timeout, this, &Widget::TimeUpdate);
    }
    
    void Widget::TimeUpdate()
    {
    	QString t = QDateTime::currentDateTime().toString("yyyy-MM-dd hh:mm:ss");
    	ui->label->setText(t);
    }
    

2.事件分发器

1.概述

  • 在Qt中,事件分发器(EventDispatcher)是⼀个核⼼概念,⽤于处理GUI应⽤程序中的事件
    • 属于Qt事件机制背后的一些逻辑
    • 杀伤力比较广,不当使用可能对现有逻辑造成一些负面影响,一般不建议使用
  • 事件分发器负责将事件从⼀个对象传递到另⼀个对象,直到事件被处理或被取消
  • 每个继承⾃QObject类或QObject类本⾝都可以在本类中重写bool event(QEvent* e),来实现相关事件的捕获和拦截

2.事件分发器工作原理

  • 在Qt中,发送的事件都是传给了QObject对象,更具体点是传给了QObject对象的event()
    • 所有的事件都会进⼊到这个函数⾥⾯
      • 那么处理事件就要重写这个event()函数
    • event()函数本⾝不会去处理事件,⽽是根据事件类型(type)调⽤不同的事件处理函数
  • 事件分发器就是⼯作在应⽤程序向下分发事件的过程中
    • 事件分发器⽤于分发事件,在此过程中,事件分发器也可以做拦截操作
    • 事件分发器主要是通过bool event(QEvent* e)来实现
      • 返回值:若为ture,代表拦截,不向下分发
        请添加图片描述

3.使用

  • Qt中的事件是封装在QEvent类中,其所包括的事件类型:

    请添加图片描述

  • 示例:拦截鼠标左键单击事件

    void Widget::mousePressEvent(QMouseEvent* event)
    {
    	if(event->button() == Qt::LeftButton)
    	{
    		qDebug() << "鼠标左键被按下";
    	}
    }
    
    bool Widget::event(QEvent* ev)
    {
    	if(ev->type() == QEvent::MouseButtonPress)
    	{
    		qDebug() << "Event中鼠标被按下";
    		return true; // 返回true,代表拦截,不向下分发
    	}
    
    	// 其他事件交给父类处理(默认处理)
    	return QWidget::event(ev);
    }
    

3.事件过滤器

0.是什么?

  • 在Qt中,⼀个对象可能经常要查看或拦截另外⼀个对象的事件
    • 例如:对话框想要拦截按键事件,不让别的组件接收到,或者修改按键的默认值等
    • 属于Qt事件机制背后的一些逻辑
    • 杀伤力比较广,不当使用可能对现有逻辑造成一些负面影响,一般不建议使用
  • Qt创建了QEvent事件对象之后,会调⽤QObjectevent()函数处理事件的分发,可以在event()函数中实现拦截的操作
    • 由于event()protected的,因此,需要继承已有类
    • 如果组件很多,就需要重写很多个event()
      • 这当然相当⿇烦,更不⽤说重写event()还得⼩⼼⼀堆问题
      • 好在Qt提供了另外⼀种机制来达到这⼀⽬的:事件过滤器
  • 事件过滤器是在应⽤程序分发到event事件分发器之前,再做⼀次更⾼级的拦截
    请添加图片描述

2.使用

  • 事件过滤器的⼀般使⽤步骤
    • 安装事件过滤器
    • 重写事件过滤器函数:eventfilter()
  • 示例
    {
    	void MyLabel::mousePressEvent(QMouseEvent* event)
    	{
    		QString str = QString("鼠标按下: x = %1, y = %2").
    					arg(event->x()).arg(event->y());
    		qDebug() << str.toUtf8().data();
    	}
    
    	void MyLabel::event(QEvent* ev)
    	{
    		if(ev->type() == QEvent::MouseButtonPress)
    		{
    			QMouseEvent* event = static_cast<QMouseEvent* e>(e);
    			
    			QString str = QString("event中鼠标按下: x = %1, y = %2").
    						arg(event->x()).arg(event->y());
    			qDebug() << str.toUtf8().data();
    
    			return true; // 返回true,代表拦截,不向下分发
    		}
    	
    		// 其他事件交给父类处理(默认处理)
    		return QWidget::event(ev);
    	}
    }
    ----------------------------------------------------------------------
    {
    	// Widget构造函数中
    	{
    		// 步骤1:给label安装事件过滤器  this:当前窗口安装事件过滤器
    		ui->label->installEventFilter(this);
    	}
    
    	// 步骤2:重写eventFilter事件
    	bool Widget::eventFilter(QObject* obj, QEvent* e)
    	{
    		if(obj == ui->label) // 判断控件
    		{
    			if(e->type == QEvent::MouseButtonPress)
    			{
    				QMouseEvent* event = static_cast<QMouseEvent* e>(e);
    			
    				QString str = QString("事件过滤器中鼠标按下: x = %1, y = %2").
    							arg(event->x()).arg(event->y());
    				qDebug() << str.toUtf8().data();
    
    				return true;
    			}
    		}
    	
    		// 其他事件交给父类处理
    		return QWidget::event(ev);
    	}
    }
    
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

DieSnowK

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值