目录
一、封装自定义控件
1.添加界面类
2.添加控件
3.提升封装的控件
4.实现功能
5.提供接口
6.测试接口
二、鼠标事件
前言:
1.鼠标进入事件 enterEvent
2.鼠标离开事件 leaveEvent
3.鼠标按下事件 mousePressEvent
4.鼠标释放事件 mouseReleaseEvent
5.鼠标移动事件 mouseMoveEvent
三、定时器事件
1.定时器1
1.1重写定时器事件
1.2调整定时器计数频率
2.定时器2
新的实现方式
暂停和启动
3.event事件
3.1用途:用于事件的分类
3.2拦截函数
4.事件过滤器
步骤:
(1)给控件安装事件过滤器
(2)重写 eventFilter 函数
三、绘图
1.绘图事件
高级设置
画资源图片
移动图片
自动移动
2.绘图设备
Pixmap绘图设备
QImage 绘图设备
QPicture 绘图设备
四、文件
1、文件读取操作
实现一:文件读取
实现二:读取gbk格式
实现三:文件写入
2、文件信息读取
一、封装自定义控件
源码:
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3/01_smallWidget
1.添加界面类
步骤:
添加新文件-Qt-设计师界面类(.h .cpp .ui)--smallWidget.ui

2.添加控件
smallWidget.ui中设计QSpinBox和QSlider两个控件
 
3.提升封装的控件
Widget.ui中使用自定义控件,拖拽一个Widget,右键点击提升为,写入smallWidget类名,点击添加,点击提升。成功后,widget后出现刚才添加的类名。
![]()
4.实现功能
改变数字,滑动条跟着移动,信号槽监听。
#include "smallwidget.h"
#include "ui_smallwidget.h"
smallWidget::smallWidget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::smallWidget)
{
    ui->setupUi(this);
    //QSpinBox移动 QSlider跟着移动
    void(QSpinBox:: * spSignal)(int) = &QSpinBox::valueChanged;
    connect(ui->spinBox,spSignal,
            ui->horizontalSlider,&QSlider::setValue);
    //QSlider滑动 QSpinBox数字跟着改变
    connect(ui->horizontalSlider,&QSlider::valueChanged,
            ui->spinBox,&QSpinBox::setValue);
} 
效果图展示:
无论是改变数字还是滑动条,另一方都会随之而改变。

5.提供接口
提供getNum 和 setNum 接口。需要在smallWidget.h中声明。
//位于smallWidget.cpp
//设置数字
void smallWidget::setNum(int num)
{
    ui->spinBox->setValue(num);
}
//获取数字
int smallWidget::getNum()
{
    return ui->spinBox->value();
} 
建立连接:
#include "widget.h"
#include "ui_widget.h"
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击获取 获取当前的值
    connect(ui->btn_get,&QPushButton::clicked,[=](){
        qDebug()<<ui->widget->getNum();
    });
    //设置到一半
    connect(ui->btn_set,&QPushButton::clicked,[=](){
       ui->widget->setNum(50);
    });
}
Widget::~Widget()
{
    delete ui;
}
 
6.测试接口
拖动滑动条到49,点击获取当前值,成功获取。
点击设置到一半,数字和滑动条都变为50,再次点击获取,成功获取到当前值50。

二、鼠标事件
源码:
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3/02_QtFvent
前言:
.ui界面拖拽一个label控件,调整label属性中的frameShape的值为Box。
效果图:

创建一个新类,新类继承于QLabel,有关鼠标的函数均在QLabel中。
1.鼠标进入事件 enterEvent
#include "mylable.h"
#include<QDebug>
#include<QMouseEvent>
#include<QString>
myLable::myLable(QWidget *parent) : QLabel(parent)
{
}
  //鼠标进入
  void myLable::enterEvent(QEvent *event)
  {
      qDebug()<<"鼠标进入";
  }
} 
效果图:
当鼠标移入框中,下方就会打印鼠标进入。

2.鼠标离开事件 leaveEvent
//鼠标离开
void myLable::leaveEvent(QEvent *)
{
      qDebug()<<"鼠标离开";
} 
效果图:
当鼠标移出时,下方就会打印鼠标离开。

3.鼠标按下事件 mousePressEvent
此时会打印鼠标按下同时也会打印按下的坐标;如果加上左键判断,那么只有左键按下的时候才会打印。
//鼠标按下
void myLable:: mousePressEvent(QMouseEvent *ev)
{
//    //当鼠标左键按下
//    if(ev->button() == Qt::LeftButton)
//  {
    QString str =
    QString("鼠标按下了x = %1  y = %2  globalX = %3  globalY = %4")
            .arg(ev->x()).arg(ev->y())
            .arg(ev->globalX()).arg(ev->globalY());
     qDebug()<<str;
//   }
} 
效果图:

4.鼠标释放事件 mouseReleaseEvent
//鼠标释放
void myLable:: mouseReleaseEvent(QMouseEvent *ev)
{
//    //当鼠标左键释放
//    if(ev->button() == Qt::LeftButton)
//  {
    QString str =
    QString("鼠标释放了x = %1  y = %2  globalX = %3  globalY = %4")
            .arg(ev->x()).arg(ev->y())
            .arg(ev->globalX()).arg(ev->globalY());
     qDebug()<<str;
//   }
} 
效果图:

5.鼠标移动事件 mouseMoveEvent
//鼠标移动
void myLable:: mouseMoveEvent(QMouseEvent *ev)
{
//    //当鼠标左键移动
//    //& 左右键同时按也可以触发
//    if(ev->buttons() == Qt::LeftButton)
//  {
    QString str =
    QString("鼠标移动了x = %1  y = %2  globalX = %3  globalY = %4")
            .arg(ev->x()).arg(ev->y())
            .arg(ev->globalX()).arg(ev->globalY());
     qDebug()<<str;
//   }
} 
效果图:

当同时按下鼠标左右键时,可能会出现0x00000003,此时&操作符判断为真,鼠标移动坐标打印。而==操作符则不会,只有左键按下时才触发。

当构造函数加上这句鼠标追踪代码,移动打印不用按住鼠标移动,也可以触发。
    //追踪鼠标
    setMouseTracking(true); 
三、定时器事件
源码,文件名:02_QtFvent
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3/
1.定时器1
ui界面拖拽一个label,更改frameShape的属性为Panel,使边框线清晰可见。

1.1重写定时器事件
widget.h文件中声明该成员函数。
void timerEvent(QTimerEvent * ev); 
widget.cpp中实现
void Widget:: timerEvent(QTimerEvent * ev)
{
       static int num = 1;
       //label2 每隔1秒+1
       ui->label_2->setText(QString::number(num++));
}
 
效果图:
里面的数字会每隔一秒加1。
 
1.2调整定时器计数频率
startTimer(1000);//毫秒单位
 
widget.h中声明成员变量
    int id1;//定时器1的唯一标识 
widget.cpp中实现
#include "widget.h"
#include "ui_widget.h"
#include<QString>
#include<QTimer>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{   
      id1 =  startTimer(1000);//参数1 间隔 单位 毫秒
}
void Widget:: timerEvent(QTimerEvent * ev)//timerEvent的返回值是定时器的唯一标识  可以和 
                                          //id1做比较
{
    if(ev->timerId() == id1)
    {
       static int num = 1;
       //label2 每隔1秒+1
       ui->label_2->setText(QString::number(num++));
    }
} 
2.定时器2
新的实现方式
#include "widget.h"
#include "ui_widget.h"
#include<QString>
#include<QTimer>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
   //定时器第二方式
   QTimer * timer = new QTimer(this);//创建定时器对象
   //启动定时器
   timer->start(500);
   //每隔一定毫秒,发送信号 timeout,进行监听
   connect(timer,&QTimer::timeout,[=](){
       static int num = 1;
       //label4 每隔0.5秒+1
       ui->label_4->setText(QString::number(num++));
   });
} 
暂停和启动
创建暂停,启动按钮

建立连接(widget.cpp)
   //点击暂停按钮 实现停止定时器
   connect(ui->btn,&QPushButton::clicked,[=](){
       timer->stop();
   });
   //点击启动按钮,实现启动定时器
   connect(ui->btn_1,&QPushButton::clicked,[=](){
       timer->start(500);
   }); 
效果图:

3.event事件
3.1用途:用于事件的分类

3.2拦截函数
在鼠标事件中进行拦截鼠标点击操作。
bool myLable::event(QEvent *e)
{   //如果是鼠标按下,在event事件分发中做拦截操作
    if(e->type()==QEvent::MouseButtonPress)
    {
        QMouseEvent * ev = static_cast<QMouseEvent *>(e);//类型转换,ev变e
        QString str =
        QString("Event函数中,鼠标按下了x = %1  y = %2  globalX = %3  globalY = %4")
                .arg(ev->x()).arg(ev->y())
                .arg(ev->globalX()).arg(ev->globalY());
        qDebug()<<str;
        return true;//true代表用户自己处理这个事件,不向下分发
    }
    //其他事件  交给父类处理  ,默认处理
    return QLabel::event(e);
}
 
此时,鼠标按下将不会运行原函数,只会运行拦截函数,其中按下操作可以用type()函数判断。

4.事件过滤器
程序将事件分发到事件分类前,可以利用过滤器拦截

步骤:
(1)给控件安装事件过滤器
#include "widget.h"
#include "ui_widget.h"
#include<QString>
#include<QTimer>
#include<QMouseEvent>
#include<QDebug>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
   //步骤一 安装事件过滤器
   //给label_1 安装事件过滤器
   ui->label->installEventFilter(this);
}
 
(2)重写 eventFilter 函数
   //步骤二 重写eventfilter事件
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  globalX = %3  globalY = %4")
                  .arg(ev->x()).arg(ev->y())
                  .arg(ev->globalX()).arg(ev->globalY());
          qDebug()<<str;
          return true;//true代表用户自己处理这个事件,不向下分发
      }
  }
  //其他默认处理
  return QWidget::eventFilter(obj,e);
} 
效果图:

三、绘图
03_QPainter
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3/
1.绘图事件
绘图事件的函数(widget.h)
#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 paintEvent(QPaintEvent *event);
    int posX =0;
private:
    Ui::Widget *ui;
};
#endif // WIDGET_H 
实现函数(widget.cpp)
void Widget:: paintEvent(QPaintEvent *event)
{
    //实例化画家对象 this指定绘图设备
    QPainter painter(this);
    //设置画笔
    QPen pen(QColor(255,0,0));
    //设置笔的宽度
    pen.setWidth(3);
    //设置画笔的风格
    pen.setStyle((Qt::DotLine));
    //让画家使用这个笔
    painter.setPen(pen);
    //设置画刷
    QBrush brush(QColor(0,255,0));
    //设置画刷风格
    brush.setStyle(Qt::Dense7Pattern);
    //让画家去使用画刷
    painter.setBrush(brush);
    painter.drawLine(QPoint(0,0),QPoint(100,100));
    //画圆
    painter.drawEllipse(QPoint(100,100),50,50);
    //矩形
    painter.drawRect(QRect(20,20,50,50));
    //画文字
    painter.drawText(QRect(10,200,100,50),"好好学习,天天向上");
} 
效果图:

高级设置
    //高级设置 ///
    QPainter painter(this);
    painter.drawEllipse(QPoint(100,50) , 50,50);
    //设置 抗锯齿能力  效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50) , 50,50);
    //画矩形
    painter.drawRect(QRect(20,20,50,50));
    //移动画家,其实就是改变画笔的落下的位置
    painter.translate(100,0);
    //保存画家状态
    painter.save();
    painter.drawRect(QRect(20,20,50,50));
    painter.translate(100,0);
    //还原画家保存状态
    //painter.restore();
    painter.drawRect(QRect(20,20,50,50)); 
若不还原画家的状态,矩形有三个;若还原了,能看到矩形有两个,因为有两个矩形画重叠了。
效果图:
 

画资源图片
    ///利用画家 画资源图片 ///
      QPainter painter(this);
      QPixmap pix = QPixmap(":/new/anniu/1.png");
      painter.drawPixmap(posX,0,pix);
 
效果图:

移动图片
添加移动按钮,使图片的位置可以随着按钮的点击而移动。
#include "widget.h"
#include "ui_widget.h"
#include<QTimer>
#include<QPainter>//画家类
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击移动按钮,移动图片
        connect(ui->pushButton,&QPushButton::clicked,[=](){
            posX+=20;
            //如果要手动调用绘图事件 用update更新
            update();
        });
} 
效果图:

自动移动
widget
        QTimer * timer = new QTimer(this);
        timer->start(10);
        connect(timer,&QTimer::timeout,[=](){
            posX++;
            update();
        }); 
painterEventh函数
      //如果超出屏幕 从0开始
       if(posX >= this->width())
       {
           posX = 0;
       } 
2.绘图设备
04_QtPaintDevice
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3/
Pixmap绘图设备
#include "widget.h"
#include "ui_widget.h"
#include<QPixmap>
#include<QPainter>
#include<QPicture>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //Pixmap绘图设备 专门为平台做了显示的优化
    QPixmap pix(300,300);
    //填充颜色
    pix.fill(Qt::white);
    //声明画家
    QPainter  painter(&pix);
    painter.setPen(QPen(Qt::green));
    painter.drawEllipse(QPoint(150,150),100,100);
    //保存
    pix.save("E:\\pix.png");
} 
QImage 绘图设备
    //QImage 绘图设备  可以对像素进行访问
    QImage img(300,300,QImage::Format_RGB32);
    img.fill(Qt::white);
     //声明画家
     QPainter  painter(&img);
     painter.setPen(QPen(Qt::blue));
     painter.drawEllipse(QPoint(150,150),100,100);
     img.save("E:\\img.png"); 
修改像素 (需要添加资源文件)
void Widget::paintEvent(QPaintEvent *)
{
        QPainter painter(this);
        //利用QImage 对像素进行修改
        QImage img;
        img.load(":/image/Luffy.png");
        //修改像素点
        for(int i = 50;i<100;i++)
        {
            for(int j = 50;j<100;j++)
            {
                QRgb value = qRgb(255,0,0);
                img.setPixel(i,j,value);
            }
        }
         painter.drawImage(0,0,img);
} 
效果图:
 
QPicture 绘图设备
    //QPicture 绘图设备 可以记录和重现绘图指令
    QPicture pic;
    QPainter painter;
    painter.begin(&pic);//开始往pic上画
    painter.setPen(QPen(Qt::cyan));
    painter.drawEllipse(QPoint(150,150),100,100);
    painter.end();//结束画画
    pic.save("E:\\pic.zt"); 
保存的文件无法打开,只能用下面的代码打开。
void Widget::paintEvent(QPaintEvent *)
{
  QPainter painter(this);
    //重现QPictrue的绘图指令
    QPicture pic;
    pic.load("E:\\pic.zt");
    painter.drawPicture(0,0,pic);
} 
四、文件
05_Qtfile
https://gitee.com/liu-wei-hao123/green_C/tree/master/Day3
1、文件读取操作
新建布局
lineEdit和QPushButton,入widget中,选择水平布局。
testEdit放入Widget中,选择垂直布局。

实现要求:
- 点击选取文件按钮,弹出文件对话框;
 - 文件路径放到lineEdit中;
 - 读取内容放入textEdit中;
 
实现一:文件读取
#include<QFile>
#include<QTextCodec>
#include<QFileInfo>
#include<QDebug>
#include<QDateTime>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
    //点击选取文件按钮 弹出文件对话框
        connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName
        (this,"打开文件","D:\\word\\Everlasting Regret");
        //文件路径放到lineEdit中
        ui->lineEdit->setText(path);
        //读取内容 放入到textEdit中
        //默认支持格式utf8
        QFile file(path);
        
        //设置打开方式
        file.open(QIODevice::ReadOnly);
        QByteArray array = file.readAll();//文件内容全部读取到array中
        ui->textEdit->setText(array);
        file.close();
}
 
循环读取每一行或只读取一行
 QByteArray array;
 while(!file.atEnd())
 {
   array += file.readLine();//按行读
 }
   //array = file.readLine();//按行读取 
结果图:

实现二:读取gbk格式
如果想读取gbk格式的文件,我们可以进行文件格式转换。
        //编码格式类
        QTextCodec * codec = QTextCodec::codecForName("gbk"); 
        ui->textEdit->setText(codec->toUnicode(array)); 
实现三:文件写入
程序运行结束后,再打开文件放可以看到写入内容。
 //进行写文件
 file.open(QIODevice::Append);//用追加的方式进行写
 file.write("啊啊啊啊");
 file.close(); 
2、文件信息读取
        //QFileInfo 文件信息类
        QFileInfo info(path);
        qDebug()<<"大小:"<<info.size()
                <<"后缀名:"<<info.suffix()
                <<"文件名称:"<<info.fileName()
                <<"文件路径:"<<info.filePath();
        qDebug()<<"创建日期:"<<info.created().toString("yyyy/MM/dd hh:mm:ss");
        qDebug()<<"最后修改日期:"<<info.lastModified().toString("yyyy-MM-dd hh:mm:ss");
    }); 
结果图:

第三天的学习记录分享完毕,关注我,带你了解更多的编程知识。
看到这里,不妨点个攒,关注一下吧!

最后,谢谢你的观看!



















