自学内容网 自学内容网

Qt学习记录(C++)——Day 3

目录

一、封装自定义控件

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_QtFventicon-default.png?t=N7T8https://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_QPaintericon-default.png?t=N7T8https://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_QtPaintDeviceicon-default.png?t=N7T8https://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_Qtfileicon-default.png?t=N7T8https://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");

    });

结果图:

第三天的学习记录分享完毕,关注我,带你了解更多的编程知识。

看到这里,不妨点个攒,关注一下吧!

最后,谢谢你的观看!


原文地址:https://blog.csdn.net/a9437578h/article/details/137400501

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!