• QT7_视频知识点笔记_3_自定义控件,事件处理器⭐,定时器,QPainter,绘图设备,不规则窗口


    第三天:

    自定义控件,事件处理器⭐,定时器,QPainter,绘图设备,不规则窗口实现
    1.自定义控件:
    创建新的QT控件类,然后再需要使用的地方--》提升为   来使用
    
    • 1

    如何使用基础控件的信号和槽函数(),一个改变另外一个也跟着进行改变(重点:已知类帮助文档查找信号和槽或函数)

    //使用信号槽来完成功能
        //调节数字控件,则横向的数值会跟着变动
        //QSpinBox::valueChanged有函数重载,需要使用指针的形式
        void (QSpinBox::*SigValueChange) (int) = &QSpinBox::valueChanged;
        connect(ui->spinBox,SigValueChange,ui->horizontalSlider,&QSlider::setValue);
        //调节横向数值,数字控件会跟着移动
        connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    2.事件处理器

    鼠标事件为例,键盘和其他事件类似
    创建一个MyLabel类,继承自QLabel类,在其帮助文档的可重写函数中或者其基类中找需要的事件函数,然后进行重写。以鼠标进入,鼠标离开,鼠标按下,定时器(其本质是回调函数,不用我们自己调用,只需要重写,条件满足会自动调用)

    public:
        explicit MyLabel(QWidget *parent = 0);//继承自一个窗口类
        
    protected:
        //是受保护的成员变量(在QLabel的基类QWidget中可以找到该函数)
        //鼠标进入
        void enterEvent(QEvent *);
        //鼠标离开
        void leaveEvent(QEvent *);
        //鼠标按下
        void mousePressEvent(QMouseEvent *event);
        //定时器
        void timeEvent(QTimerEvent *);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    //要注意要加:QLabel(parent),要不然无法显示
    MyLabel::MyLabel(QWidget *parent):QLabel(parent)
    {
        this->setText("hello");
    }
    void MyLabel::enterEvent(QEvent *)
    {
        setText("enterEvent");
    }
    
    void MyLabel::leaveEvent(QEvent *)
    {
        setText("leaveEvent");
    }
    
    void MyLabel::mousePressEvent(QMouseEvent *ev)
    {
        //从帮助文档中可查看QMouseEvent的使用
        if(ev->button() == Qt::LeftButton )
        {
            setText("mousePressEvent:Qt::LeftButton!");
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    3.定时器:

    方法a:重写定时器事件函数

    //定时器
    void timerEvent(QTimerEvent *);
        
    //每触发一次定时器,都进入该函数中
    void MyLabel::timerEvent(QTimerEvent *)
    {
        static int num = 0;
        QString str = QString("%1").arg(num++);
        setText(str);
        if(num == 100)
        {
            killTimer(timeID);  //根据定时器开始时的返回ID去关闭定时器
        }
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15

    启动定时器,此处启动在构造函数中

    MyLabel::MyLabel(QWidget *parent):QLabel(parent)
    {
        this->setText("hello");
    
        //启动定时器
        timeID = startTimer(100);//每隔100ms启动一次
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    方法b:添加QTimer类,创建对象,在计时到之后会发出信号,使用信号槽进行处理。(推荐这种写法)

    //第二种定时器
        QTimer *timer1 = new QTimer(this);
        timer1->start(100);//100ms触发一次
        //timer1发出了信号,创建槽函数进行接收
        connect(timer1,&QTimer::timeout,this,[=](){
            static int number;
            this->setText(QString::number(number++));
    
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    4.QPainter绘图和QPaintDevice(QPixMap,QBitmap,QImage,QPicture)绘图设备

    a.需要绘图,先添加绘图类QPainter,然后需要重写虚函数

    #include 
    .......
    protected:
        //1.虚函数(可重写)
        //2.回调函数(不需要用户去主动调用,在刷新窗口的时候会自动调用:窗口显示,最大化最小化,窗口被遮挡,重新显示时,用户强制刷新,...)
        //3.如果想使用画家类在窗口中画图,操作必须在paintEvent函数中完成
        void paintEvent(QPaintEvent *event) ;
    
    ......
    void Study_Painter::paintEvent(QPaintEvent *event)
    {
        //绘图类重写虚函数绘图事件
        //创建画家类对象
        QPainter p(this);   //指定绘图设备--》在this当前窗口中画
    	//根据提示(帮助文档写参数及其类型)
        //画背景图
        p.drawPixmap(0,0,QPixmap("D://321.jpg"));
    
        //画直线
        p.drawLine(QPoint(200,200),QPoint(300,300));
    
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22

    显示结果:
    在这里插入图片描述
    创建画笔:(更改颜色等功能)-----轮廓

        QPen pen;
        pen.setColor(QColor(0,255,100));
        pen.setWidth(10);
        p.setPen(pen);	//将设置的pen传入给QPainter画家,然后再使用画家P进行画图操作
        
        p.drawPie(QRect(100,100,20,20),20,20);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    创建画刷类:QBush(闭合区域可使用画刷),使用方式跟QPen类似(p.setBrush(…))
    字体:QFont类,使用方式也类似,创建之后加入到画家类中(p.setFont(…))

    paintEvent重载后,用户如何强制刷新界面(update(); )
    void Study_CarManager::paintEvent(QPaintEvent *event)
    {
        QPainter p(this);
        //添加
        x += 5;
        p.drawPixmap(x,100,QPixmap("D://myheart.png"));
        if(x > this->width())
        {
            //如果突破图片边界,则返回
            x = 20;
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    在构造函数中,检测到按钮按下,则移动图片位置(强制刷新)

    	x = 200;//注意在.h文件中和刷新
        //按下按钮刷新图片位置
        connect(ui->pushButton,&QPushButton::clicked,this,[=](){
            update();       //用户强制主动刷新,使用update会调用paintEvent
        });
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    5.QPaintDevice(QPixMap⭐,QBitmap,QImage,QPicture)绘图设备

    主要使用QPixmap来显示图片,他针对于显示器显示做了特殊优化,依赖于平台,只能在主线程中使用(UI线程)
    QImage,图片类,不依耐平台,可以在多线程中对其进行操作
    使用方法:(绘图设备,画家类,画笔)

        //绘图设备画图,QImage是类似的
        QPixmap pix(300,300);   //纸张的大小
        pix.fill(Qt::red);
        QPainter p(&pix);   //创建画家类在绘图设备上作画
        //p.begin(&pix);	//如果之前有画家类则可使用begin函数更改绘图设备
        p.setPen(QPen(Qt::green));  //为画家类创建画笔提供使用
        p.drawRect(10,10,280,280);
        pix.save("D://mypixmap.png");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    而QPicture只是保存的二进制文件,不是一个图片,保存的是绘图步骤,但是可根据QPicture的load函数传入一张之前保存的步骤图,然后drawPicture可正常绘图(可进行加密)。

    6.绘制不规则窗口

    怎样做一个不规则的窗口(边框去掉,背景设为透明,则只看见不透明的图片部分)

    //在.h中
    //1.把绘图设备设为全局可用
    QPixmap pix;        //绘图设备
    //2.重写绘图函数
    protected:
        void paintEvent(QPaintEvent *event) ;
    
    //.cpp中
    //1.在构造函数中加载所需图片
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        //1.加载图片,需要背景是透明的
        pix.load("D://myheart.png");
        //2.去掉窗口边框
        this->setWindowFlags(Qt::FramelessWindowHint);    //窗口设置
        //3.设置背景透明
        this->setAttribute(Qt::WA_TranslucentBackground);
    }
    
    //2.在paintEvent中使用画家类进行图片刷新
    void Widget::paintEvent(QPaintEvent *event)
    {
        //在窗口中把图片画出来
        QPainter p(this);
        p.drawPixmap(0,0,pix);  //把绘图设备导入画家类
    }
    
    
    
    • 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

    效果:
    在这里插入图片描述
    如果需要跟随鼠标移动,或者鼠标右键关闭窗口,则在加入鼠标的事件处理器,重写对应的事件函数(例如:mousePressEvent,mouseMoveEvent等)则可。【需注意坐标点的转换】

  • 相关阅读:
    从 Clickhouse 到 Snowflake(一): 云原生
    Java EE进阶2
    国际贸易详解:国际贸易主要有哪些分类标准和运输方式
    python爬虫基础-request请求头
    Apache Storm 2.5.0 集群安装与配置
    【Mars3d】进行水平测量measure.area({的时候,会被模型遮挡的处理方法
    IDEA找不到Maven窗口
    HTML5、CSS3、ES6新特性总结
    Nginx配置实例-负载均衡
    第六课 ceph基础学习-Ceph的管理监控和故障排查
  • 原文地址:https://blog.csdn.net/xy_77777/article/details/138539979