• c++学习27qt(三)Qt自定义控件封装,事件处理,绘画和文件读写


    Qt自定义控件封装

    步骤

    1. 添加类 Qt-设计师界面类 .h .cpp .ui
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述
      此时就添加成功
    2. 选择一个QWidget控件,添加到主界面,右击选择提升为
      . 在这里插入图片描述
      此时,我们要将1步骤的Qt界面设计类添加进去,选择提升
      如果

    在这里插入图片描述
    则说明替换成功

    1. 设置自定义控件封装内组件之间的联动效果,在.cpp文件中设置
    smallWiget::smallWiget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::smallWiget)
    {
        ui->setupUi(this);
        //QSpinBox移动 QSlider跟着移动
        void(QSpinBox:: *spinSignal)(int) = &QSpinBox::valueChanged;
        connect(ui->spinBox,spinSignal,ui->horizontalSlider,&QSlider::setValue);
    
        //QSlider移动 QSpinBox 跟着改变
    
        connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    1. 设置一些接口,供外部去使用 :(在.h文件中声明,在.cpp文件中实现)
    //smallWiget.h文件中
    class smallWiget : public QWidget
    {
        Q_OBJECT
    
    public:
        explicit smallWiget(QWidget *parent = 0);
        //定义的方法:
        void setData(int val);
        int getData();
        //end
        ~smallWiget();
    
    private:
        Ui::smallWiget *ui;
    };
    //smallWiget.cpp文件
    void smallWiget::setData(int val){
        ui->spinBox->setValue(val);
    }
    
    int smallWiget::getData(){
        return ui->spinBox->value();
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    1. 外部的简单使用
     //获取按钮
        connect(ui->btn_getValue,&QPushButton::clicked,[=](){
            qDebug()<<"当前的数值为:"<< ui->widget->getData();
        });
        //设置一半按钮
        connect(ui->btn_setHalf,&QPushButton::clicked,[=](){
            ui->widget->setData(50);
        });
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 效果展示
      请添加图片描述

    Qt中的事件处理

    捕获QLabel中的鼠标事件

    如果我们想捕获QLabel的鼠标事件,而控件本身的事件无法满足需求,就需要我们重写其方法来满足需求
    这样我们就需要创建一个类去继承QLabel,再在界面中添加一个空的容器,使其提升,再在其头文件中声明需要的方法,在.cpp文件中对具体需求做实现

    鼠标的一些事件:

    • 鼠标进入enterEvent
    • 鼠标离开leaveEvent
    • 鼠标按下mousePressEvent
    • 鼠标释放mouseReleaseEvent
    • 鼠标移动mouseMoveEvent
    • 设置鼠标追踪 this->setMouseTracking(true); 默认是true

    定时器

    定时器事件

     void timerEvent(QTimerEvent *e);
    
    • 1

    可以通过e获取定时器的id

    e->timerId();
    
    • 1

    通过定时器的id,我们可以在开启不同的定时器,做出不同的实现
    如:

    void Widget::timerEvent(QTimerEvent *e){
        //使用QTimerEvent的timeId()方法拿到具体的开启定时器的值
        if(e->timerId()==id1){
            static int num =1;
            //加上static 使其就初始化一次,如果不加static那么num会在timerEvent()方法运行时一直走,导致显示的一直是1
            ui->label->setText(QString::number(num++));
        }else{
            static int num2 =10;
            ui->label_2->setText(QString::number(num2+=10));
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    当我们有多个定时器时,我们可以使用定时器的类QTimer去创建定时器,使代码更便于管理
    如:

    //利用定时器的类QTimer实现定时功能
        QTimer * timer = new QTimer(this);
        //启动定时器
        timer->start(500);
        connect(timer,&QTimer::timeout,[=](){
           //定时功能
            static int num3 = 9;
            ui->label_3->setText(QString::number(num3+=9));
        });
    //关闭定时器(这里没有用槽和信号,尽量用事件或方法去包裹使用,再不济加个判断
    timer->stop();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11

    注意:两个实现定时器的方法没有优劣之分,按照需求选择合适的就可

    事件分发器

    1. bool event(QEvent *e)
    2. e->type()所有Qt中的事件
    3. 事件分发器可以做事件的拦截操作,如果用户进行了拦截,在对应事件里返回true代表自己处理事件

    事件过滤器

    使用事件过滤器可以做更高级拦截

    使用事件过滤器有两步:

    1. 给对应的控件安装事件过滤器
    ui->label->installEventFilter(this);
    
    • 1
    1. 重写eventFilter
    //.h
    bool eventFilter(QObject *watched, QEvent *event);
    
    //.cpp
    bool Widget::eventFilter(QObject *watched, QEvent *event){
        //参数1 对比控件  参数2对比事件
        //对比控件
        if(obj==ui->label){
            //对比事件
            if(event->type()==QEvent::MouseButtonPress){
                //处理方式
            return true;   //如果返回true 代表用户自己处理 
            }
        }    
        return QWidget::eventFilter(obj,event);//默认处理    
    }
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17

    绘画

    基本绘画

    1. 绘画方法
    //绘画事件
        void paintEvent(QPaintEvent *event);
    
    • 1
    • 2
    1. 声明画家
     //声明一个画家的对象 在窗口设备中绘制图片
        QPainter painter(this);
    
    • 1
    • 2
    1. 设置画笔
    //指定画笔
        QPen pen(QColor(255,0,0));
        //设置笔宽
        pen.setWidth(3);
        //设置笔风格
        pen.setStyle(Qt::DotLine);
        //给画家拿个笔
        painter.setPen(pen);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 设置画刷
    //画刷 用来填充画家画出的封闭图形
        QBrush brush(Qt::cyan);
        //设置画刷风格
        brush.setStyle(Qt::Dense6Pattern);
        //给画家设置画刷
        painter.setBrush(brush);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    1. 绘制一些基础图形
     //画线
        painter.drawLine(QPoint(0,0),QPoint(100,100));
        //画圆(椭圆)当rx=ry时,画出的就是一个圆
        painter.drawEllipse(QPoint(100,100),50,50);
        //画矩形 QRect()四参数说明,前面两个代表坐标,后面两个代表宽高
        painter.drawRect(QRect(20,20,50,50));
        //画文字 前面的参数代表一个矩形范围,后面的参数是目标文字
        painter.drawText(QRect(10,200,120,100),"好好学习,天天向上");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    1. 效果展示
      在这里插入图片描述

    高级绘画设置

    1.设置抗锯齿

       painter.drawEllipse(QPoint(100,100),50,50);
    //   //设置抗锯齿 效率更低,但图片更清晰
      painter.setRenderHint(QPainter::Antialiasing);
      painter.drawEllipse(QPoint(250,100),50,50);
    
    • 1
    • 2
    • 3
    • 4

    在这里插入图片描述
    2.移动画家的位置

     painter.drawRect(QRect(20,20,50,50));
       //移动画家的位置,画家初始位置为(0,0) 下面将(100,0)当作(0,0)去使用
       painter.translate(QPoint(100,0));
       painter.save();//保存画家的位置
       painter.drawRect(QRect(20,20,50,50));
       //移动画家的位置,画家初始位置为(0,0) 下面将(100,0)当作(0,0)去使用
       painter.translate(QPoint(100,0));
       //将画家的位置还原到上一次
       painter.restore();
       painter.drawRect(QRect(20,20,50,50));
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述
    3. 利用画家绘制资源图片

    #include "widget.h"
    #include "ui_widget.h"
    #include
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
        posX =10;
        //点击按钮实现图片移动
        connect(ui->pushButton,&QPushButton::clicked,[=](){
            //手动调用paintEvent函数,利用update
            posX+=20;
            update();
        });
    }
    void Widget::paintEvent(QPaintEvent *event){
       QPainter painter(this);
       //如果超过屏幕的范围,将posX设置回来
       if(posX>this->width()){
           posX =10;
       }
       //利用画家绘制图片
       painter.drawPixmap(posX,100,QPixmap(":/image/page.png"));
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    
    • 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

    效果图
    请添加图片描述

    绘图设备

    绘图设备有一下几种:

    QPixmap , QBitmap , QImage , QPicture , QWidget

    QPixmap

    QPixmap做绘图设备
    在不同平台做了显示的优化

    QPixmap简单使用案例

    //QPixmap做绘图设备
        //在不同平台做了显示的优化
        QPixmap pix(300,300);
        pix.fill(Qt::white); //设置QPixmap的填充色,默认是黑色
        QPainter painter(&pix);
        painter.setPen(QPen(Qt::blue));
        painter.drawEllipse(QPoint(150,150),100,100);
        //保存
        pix.save("E:\\pix.png");
    
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    在这里插入图片描述

    QImage

    QImage做绘图设备
    可以对像素进行访问

     QImage img(300,300,QImage::Format_RGB32);
        img.fill(Qt::white);
        QPainter painter(&img);
        painter.setPen(QPen(Qt::green));
        painter.drawEllipse(QPoint(150,150),100,100);
        img.save("E:\\img.png");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    QPicture

    QPicture做绘图设备
    记录和重现QPainter的各条命令
    这个就比较有意思了,我们可以设置生成文件的格式,并且如果不是常规默认的后缀名,那么就只有我们的Qt程序可以去打开它了

    #include "widget.h"
    #include "ui_widget.h"
    #include
    #include
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
       //QPicture做绘图设备
        //记录和重现QPainter的各条命令
        QPicture pic;
        QPainter painter;
        painter.begin(&pic);//开始执行命令,且绑定绘图设备
        painter.setPen(QPen(Qt::blue));
        painter.drawEllipse(QPoint(150,150),100,100);
        painter.end();//结束执行命令
        pic.save("E:\\pic.wjl");//保存
        //这个格式后缀可以随便写,只要不是常规默认,是没办法直接打开预览的
    }
    
    void Widget::paintEvent(QPaintEvent *event){
        //重现QPicture 的绘图命令
        QPainter painter(this);
        QPicture pic;
        pic.load("E:\\pic.wjl");
        painter.drawPicture(0,0,pic);
    
    }
    Widget::~Widget()
    {
        delete ui;
    }
    
    
    • 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
    • 33
    • 34

    在这里插入图片描述
    QBitmap 色深限定为1 ,只有黑白色

    QFile 文件读写

    规律

    和c++的方式一样,只是更换了类,还是需要路径作为文件的参数,且需要指定的打开方式,且其有默认的编码格式为utf-8

    案例

    #include "widget.h"
    #include "ui_widget.h"
    #include
    #include
    #include
    Widget::Widget(QWidget *parent) :
        QWidget(parent),
        ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        // 实现效果: 点击按钮 选择文件
        connect(ui->pushButton,&QPushButton::clicked,[=](){
            //拿到文件路径
          QString filePath =  QFileDialog::getOpenFileName(this,"选择文件","E:\\weixintool\\微信web开发者工具") ;
          //将文件路径设置到lineEdit中
          if(filePath.isEmpty()){
              QMessageBox::warning(this,"打开失败","文件路径为空");
              return;
          }
          ui->lineEdit->setText(filePath);
    
          //设置编码格式
          QTextCodec *code = QTextCodec::codecForName("gbk");//默认的编码格式是utf-8
          //将文件中的内容放入到textEdit中
          QFile file(filePath);//设置目标文件
          //设置打开方式
          file.open(QIODevice::ReadOnly);//以只读的方式打开
          QByteArray arr;
          //读取全部的方式:
          //arr = file.readAll();
    
          //按行读取
          while(!file.atEnd()){
              arr += file.readLine();
          }
          //显示arr数据
          ui->textEdit->setText(arr);
          //使用设置好的编码格式
    //      ui->textEdit->setText(code->toUnicode(arr));
    
          //用完后要关闭文件对象
          file.close();
    
          //写文件
          file.open(QIODevice::Append);//利用追加的方式写入
          file.write("这是添加的条目");
          file.close();
        });
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    
    • 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
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47
    • 48
    • 49
    • 50
    • 51
    • 52
    • 53
    • 54
    • 55
    • 56

    请添加图片描述

    QFileInfo类

    直接使用:

    //文件信息类
          QFileInfo info(filePath);
          qDebug()<<"大小"<<info.size()<<"后缀名:"<<info.suffix()<<"文件名:"<<info.fileName()<<"文件的完整路径:"
                 <<info.absoluteFilePath();
          qDebug()<<"创建日期"<<info.created().toString("yyyy/MM/dd hh:mm:ss");
          qDebug()<<"最后修改的日期"<<info.lastModified().toString("yyyy-MM-dd hh:mm:ss");
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    如果使用与日期有关的,需要导入QDate类
    利用文件的后缀名,可以做过滤文件的作用(这里不展示)
    在这里插入图片描述

  • 相关阅读:
    Redisson实现延迟队列
    java算法学习索引之二叉树问题
    开发盲盒应该具有哪些特点
    【七】http服务器开发--客户端请求格式和服务器响应格式
    下一代Vuex(Pinia)不学你就out了
    web入门---tomcat&请求响应
    项目平台——测试报表的实现(六)
    Spring自动装配
    react源码分析:组件的创建和更新
    学生家乡网页设计作品静态HTML网页—— HTML+CSS+JavaScript制作辽宁沈阳家乡主题网页源码(11页)
  • 原文地址:https://blog.csdn.net/qq_46066548/article/details/127430306