
目录
- 引出
 - 定时器事件
 - QTimerEvent
 - QTimer
 
- 事件的分发
 - 事件过滤器
 
- 总结
 - QT中的鼠标事件
 - 定义QLable的鼠标进入离开事件
 - 提升为myLabel
 - 重写QLabel的函数
 - 鼠标的事件
 - 鼠标的左中右键枚举
 - 鼠标多事件获取和鼠标移动
 - 鼠标追踪
 
- QT中的信号和槽
 - 自定义信号和槽
 - 1.自定义信号
 - 2.自定义槽
 - 3.建立连接
 - 4.进行触发
 
- 自定义信号重载
 - 带参数的
 - 按钮触发
 - 信号触发信号
 - 拓展
 
- lambda表达式
 - 返回值
 - mutable修饰
 - 案例
 
引出
QT学习(6)——QT中的定时器事件,两种实现方式;事件的分发event,事件过滤器

定时器事件
QTimerEvent


#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE
class Widget : public QWidget
{
    Q_OBJECT
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    // 重写定时器事件
    void timerEvent(QTimerEvent *);
    int id1; // 定时器1的唯一标识
    int id2; // 定时器2的唯一标识
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H
 

如何定义多个定义器事件

#include "widget.h"
#include "ui_widget.h"
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 启动定时器
    // 参数1 间隔 单位 毫秒
    id1 = startTimer(1000);
    id2 = startTimer(2000);
}
void Widget::timerEvent(QTimerEvent * ev)
{
    if(ev->timerId()==id1){
        static int num =1;
        // label1 每间隔1秒
        ui->label_2->setText(QString::number(num++));
    }
    // label2 每间隔2s
    if(ev->timerId()==id2){
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
    // label3 每间隔3s
}
Widget::~Widget()
{
    delete ui;
}
 
QTimer

定时器实现的另一种方式:实例化定时器QTimer 然后加到对象树上

进行定时信号的发送和处理


#include "widget.h"
#include "ui_widget.h"
#include <QTimer> // 定时器的类
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 启动定时器
    // 参数1 间隔 单位 毫秒
    id1 = startTimer(1000);
    id2 = startTimer(2000);
    // 定时器的第二种方式,实例化,加到对象树上
    QTimer *timer = new QTimer(this);
    //  启动定时器
    timer->start(500); // 每隔500ms
    connect(timer,&QTimer::timeout,
            [=](){
        static int num = 1;
        ui->label_4->setText(QString::number(num++));
    });
    // 点击暂停按钮,停止定时器
    connect(ui->btnStop,&QPushButton::clicked,
            [=](){
        timer->stop();
    });
}
void Widget::timerEvent(QTimerEvent * ev)
{
    if(ev->timerId()==id1){
        static int num =1;
        // label1 每间隔1秒
        ui->label_2->setText(QString::number(num++));
    }
    // label2 每间隔2s
    if(ev->timerId()==id2){
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
    // label3 每间隔3s
}
Widget::~Widget()
{
    delete ui;
}
 
事件的分发


通过重写event事件分发器,拦截鼠标按下的的事件

事件的枚举类型


静态类型转换方法

鼠标按下的事件拦截,自己处理,返回True;
其他事件交给父类进行处理,默认处理;

bool myLabel::event(QEvent *e)
{
    // 如果是鼠标按下,在event事件分发中做拦截操作
    if(e->type()==QEvent::MouseButtonPress)
    {
        QString str1 = QString("鼠标按下了,在event事件分发中处理");
        qDebug() << str1;
        // 需要进行类型转换
        QMouseEvent * ev = static_cast<QMouseEvent *>(e);
        QString str = QString("鼠标按下了,x=%1,y=%2; global坐标为:x=%3,y=%4")
                .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
        return true; // 代表用户自己处理,不向下分发
    }
    // 其他事件,交给父类处理,默认处理
    return QLabel::event(e);
}
 
事件过滤器

可以在event之前,再做一次高级的拦截

步骤:1.给label1安装事件过滤器

步骤二:重写事件过滤器的事件

这里有两个参数,obj 和 e,一个用于判断控件,另一个用来判断事件

#include "widget.h"
#include "ui_widget.h"
#include <QTimer> // 定时器的类
#include <QDebug>
#include <QMouseEvent>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    // 启动定时器
    // 参数1 间隔 单位 毫秒
    id1 = startTimer(1000);
    id2 = startTimer(2000);
    // 定时器的第二种方式,实例化,加到对象树上
    QTimer *timer = new QTimer(this);
    //  启动定时器
    timer->start(500); // 每隔500ms
    connect(timer,&QTimer::timeout,
            [=](){
        static int num = 1;
        ui->label_4->setText(QString::number(num++));
    });
    // 点击暂停按钮,停止定时器
    connect(ui->btnStop,&QPushButton::clicked,
            [=](){
        timer->stop();
    });
}
void Widget::timerEvent(QTimerEvent * ev)
{
    if(ev->timerId()==id1){
        static int num =1;
        // label1 每间隔1秒
        ui->label_2->setText(QString::number(num++));
    }
    // label2 每间隔2s
    if(ev->timerId()==id2){
        static int num2 = 1;
        ui->label_3->setText(QString::number(num2++));
    }
    // 给label1安装事件过滤器
    // 步骤1:安装事件的过滤器
    ui->label->installEventFilter(this);
}
bool Widget::eventFilter(QObject * obj, QEvent * e){
    if(obj == ui->label){
        if(e->type() == QEvent::MouseButtonPress){
            QMouseEvent * ev = static_cast<QMouseEvent *>(e);
            QString str = QString("事件过滤器===鼠标按下了,x=%1,y=%2; global坐标为:x=%3,y=%4")
                    .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
            qDebug() << str;
            return true;
        }
    }
    // 其他默认处理
    return QWidget::eventFilter(obj,e);
}
Widget::~Widget()
{
    delete ui;
}
 
总结
QT学习(6)——QT中的定时器事件,两种实现方式;事件的分发event,事件过滤器
QT中的鼠标事件


定义QLable的鼠标进入离开事件
注意这里的QWidget后面要改成QLabel


#include "mylabel.h"
#include <QDebug>
myLabel::myLabel(QWidget *parent) : QLabel(parent)
{
}
// 鼠标进入
void myLabel::enterEvent(QEvent *event)
{
    qDebug() << "鼠标进入了";
}
// 鼠标离开
void myLabel::leaveEvent(QEvent *)
{
    qDebug() << "鼠标离开了";
}
 
提升为myLabel


重写QLabel的函数
鼠标的事件

基于控件的


鼠标的左中右键枚举


鼠标多事件获取和鼠标移动


头文件
#ifndef MYLABEL_H
#define MYLABEL_H
#include <QLabel>
class myLabel : public QLabel
{
    Q_OBJECT
public:
    explicit myLabel(QWidget *parent = nullptr);
    // 鼠标进入
    void enterEvent(QEvent *event);
    // 鼠标离开
    void leaveEvent(QEvent *);
    // 鼠标放下和释放
    virtual void mousePressEvent(QMouseEvent *ev);
    virtual void mouseReleaseEvent(QMouseEvent *ev);
    // 鼠标的移动
    virtual void mouseMoveEvent(QMouseEvent *ev);
signals:
};
#endif // MYLABEL_H
 
cpp文件
#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>
myLabel::myLabel(QWidget *parent) : QLabel(parent)
{
}
// 鼠标进入
void myLabel::enterEvent(QEvent *event)
{
//    qDebug() << "鼠标进入了";
}
// 鼠标离开
void myLabel::leaveEvent(QEvent *)
{
//    qDebug() << "鼠标离开了";
}
// 鼠标放下和释放
void myLabel::mousePressEvent(QMouseEvent *ev)
{
    // 鼠标左键按下打印
    if(ev->button() == Qt::LeftButton){
        QString str = QString("鼠标按下了,x=%1,y=%2; global坐标为:x=%3,y=%4")
                .arg(ev->x()).arg(ev->y()).arg(ev->globalX()).arg(ev->globalY());
        qDebug() << str;
    }
}
void myLabel::mouseReleaseEvent(QMouseEvent *ev)
{
    qDebug() << "鼠标释放";
}
// 鼠标的移动
void myLabel::mouseMoveEvent(QMouseEvent *ev)
{
    if(ev->buttons() & Qt::LeftButton)
    {
        qDebug() << "鼠标移动";
    }
}
 
鼠标追踪

QT中的信号和槽
自定义信号和槽
1.自定义信号
写到signals下
 返回void
 需要声明,不需要实现
 可以有参数,可以重戟

2.自定义槽
返回void
 需要声明,也需要实现
 可以有参数,可以重载
 写到public slot下或者public或者全局函数

3.建立连接

// 老师饿了,学生请吃饭
connect(te,&Teacher::hungry,st,&Student::treat);
 
4.进行触发

自定义信号重载
当自定义信号和槽出现重载
 8.1 需要利用还数指针明确指向函数的地址·
 8.2void(Teacher::tsignal )QString )=&Teacher::hungry;
 8.3 QString转成char *
 8.3.1.ToUtf80转为QByteArray
 8.3.2.Data0转为Char *
 8.4信号可以连接信号
 8.5断开信号disconnect
带参数的
    void (Teacher::*teacherSignal)(QString) = &Teacher::hungry;
    void (Student::*StudentSlot)(QString) = &Student::treat;
 


void Student::treat(QString foodName){
    // QString -> char * 先转成QByteArray(.toUtf8())  再转成Char* ()
    qDebug() << "请老师吃。。。" << foodName.toUtf8().data();
}
 
按钮触发

    // 用一个按钮调用下课
    QPushButton *btn = new QPushButton("下课了",this);
    // 重置窗口daxiao
    this->resize(600,400);
    connect(btn,&QPushButton::clicked,this,&Widget::classIsOver);
 
信号触发信号

    // 无参的信号和槽连接
    void (Teacher::*teacherSignal2)(void) = &Teacher::hungry;
    void (Student::*StudentSlot2)(void) = &Student::treat;
    connect(te,teacherSignal2,st,StudentSlot2);
    // 信号连接信号
    connect(btn,&QPushButton::clicked,te,teacherSignal2);
 
断开信号disconnect
拓展
1、信号是可以连接信号
 2、一个信号可以连接多个槽函数
 3、多个信号可以连接同一个糟函数
 4、信号和槽函数的参数必须类型一一对应
 5、信号和槽的参数个数是不是要一致?信号的参数个数可以多余槽函数的参数个数

connect(信号的发送者,发送的信号signal信号),信号接受者,槽函数SLOT)
 优点:参数直观
 缺点:编译器不会检测爸数类型:
lambda表达式






    [=](){
        btn->setText("aaa");
    }();
 
返回值

    int ret = []()->int{return 1000;}();
    qDebug() << "ret = " << ret;
 
mutable修饰

    QPushButton *myBtn1 = new QPushButton(this);
    QPushButton *myBtn2 = new QPushButton(this);
    myBtn1->move(100,100);
    int m = 10;
    connect(myBtn1,&QPushButton::clicked,this,
            [m]()mutable {m=100+10;qDebug()<< m;});
    connect(myBtn2,&QPushButton::clicked,this,
            [=](){qDebug()<<m;});
    qDebug() << m;
 
案例

    QPushButton * btnClose = new QPushButton;
    btnClose->setText("close");
    btnClose->move(100,0);
    btnClose->setParent(this);
    connect(btnClose,&QPushButton::clicked,this,
            [=](){
        btnClose->setText("关闭");
        emit te->hungry("娃哈哈");
//        this->close();
    });
                
![[数据结构] 排序#插入排序希尔排序](https://i-blog.csdnimg.cn/direct/570343accdbd428bb9d9948693d69c05.png)




![[FreeRTOS 功能应用] 互斥量 功能应用](https://i-blog.csdnimg.cn/direct/9e9f8c31a549452298de10935da1e7ce.png)












