【Qt】day3 自定义控件、框架、定时器、QPainter、QFile

文章目录

自定义控件封装

1.创建新文件-Qt-设计师界面类(.h .cpp .ui)

2.以QSpinBox和QSlider为例子。在.ui中设计这两个控件

3.在主ui中添加Widget,并把它升级。

类名称为自己在添加新文件(设计师界面类)写的。
若这个自定义控件经常用到,可以设为全局包含

  1. 添加两个按钮btn_get和btn_set

5.实现函数:改变数字,滑动条跟着移动 ,信号槽监听。在新组建.cpp中完成实现。

    //QSpinBox移动 QSlider跟着移动
    void(QSpinBox:: * spSignal)(int) = &QSpinBox::valueChanged;
    connect(ui->spinBox,spSignal,ui->horizontalSlider,&QSlider::setValue);

    //QSlider滑动 QSpiBox数字跟着改变
    connect(ui->horizontalSlider,&QSlider::valueChanged,ui->spinBox,&QSpinBox::setValue);

6.提供 getNum 和 setNum对外接口:在新组件.h声明两个函数。在新组件.cpp中实现这两个函数

自定义框架

1.创建新文件-C/C+±Class,我这里命名为myLable.

2.改3处类名

3.在头文件写函数声明

cpp 复制代码
    //鼠标进入事件
    void enterEvent(QEnterEvent *event);
    //鼠标离开事件
    void leaveEvent(QEvent *);

    //鼠标按下
    virtual void mousePressEvent(QMouseEvent *ev);
    //鼠标释放
    virtual void mouseReleaseEvent(QMouseEvent *ev);

    //鼠标移动
    virtual void mouseMoveEvent(QMouseEvent *ev);

4.在源文件实现函数

cpp 复制代码
myLabel::myLabel(QWidget *parent)
    : QLabel{parent}
{
    //设置鼠标追踪状态
    setMouseTracking(true);
}

// 鼠标进入事件
void myLabel::enterEvent(QEnterEvent *event)
{
    qDebug()<<"鼠标进入了";

}

void myLabel::leaveEvent(QEvent *)
{
    qDebug()<<"鼠标离开了";
}

//鼠标按下
void myLabel::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;
    // }


}
//鼠标释放
void myLabel::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;
    // }
}

//鼠标移动
void myLabel::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;
    // }
}
鼠标事件 代码
鼠标进入 enterEvent
鼠标离开 leaveEvent
鼠标按下 mousePressEvent ( QMouseEvent ev)
鼠标释放 mouseReleaseEvent
鼠标移动 mouseMoveEvent
鼠标坐标 ev->x() x坐标 ev->y() y坐标
判断所有按键 ev->button()
左按键/右按键 Qt::LeftButton / Qt::RightButton
判断组合按键 判断move时候的左右键 结合 & ev->buttons()
格式化字符串 QString( " %1 %2 " ).arg( 111 ).arg(222)
设置鼠标追踪 setMouseTracking(true);

定时器

第一种方式

1.在ui界面创建两个label_2和label_3

2.在widget.h中,写定时器的函数声明和2个公有变量

cpp 复制代码
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

    //重写定时器事件
    void timerEvent(QTimerEvent *);

    int id1;//定时器1的唯一标识
    int id2;//定时器2的唯一标识


private:
    Ui::Widget *ui;
};

3.在源文件写函数实现和调用定时器。

cpp 复制代码
Widget::Widget(QWidget *parent): QWidget(parent),ui(new Ui::Widget)
{
    ui->setupUi(this);
    //启动定时器
    id1 = startTimer(1000);
    id2 = startTimer(2000);
}

void Widget::timerEvent(QTimerEvent *ev)
{
    if(ev->timerId() == id1)
    { 
        static int num = 1;
        //label2 每隔1秒+1
        ui->label_2->setText(QString::number(num++));
    }
    
    if(ev->timerId() == id2)
    {
        static int num2 = 1;
        //label3 每隔2秒+1
        ui->label_3->setText(QString::number(num2++));
    }
}

第二种方式 (推荐)

1.ui界面设计两个按钮btn,btn1,一个label_4

2.在源文件,实现按键的功能和启动定时器

加入头文件<QTimer>

利用定时器类 QTimer
创建定时器对象 QTimer * timer = new QTimer(this);
启动定时器 timer->start(毫秒)

每隔一定毫秒,发送信号 timeout ,进行监听
暂停 timer->stop

事件分发器

相当于总控,在一些情况下可以屏蔽某些键位

以屏蔽"鼠标按下"为例.

1.在头文件添加函数声明

cpp 复制代码
    //通过event事件分发器 拦截 鼠标按下事件
    bool event(QEvent *e);

2.在源文件实现函数

cpp 复制代码
bool myLabel::event(QEvent *e)
{
    if(e->type()==QEvent::MouseButtonPress)
    {
        QMouseEvent * ev = static_cast<QMouseEvent *>(e); //转为QMouseEvent类型
        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;  //ture代表用户自己处理这个事件,不向下分发
    }
    //其他事件 交给父类处理 默认处理
    return QLabel::event(e);
}

3.效果如图

小结:

用途:事件的分发,也可以做拦截操作

bool event( QEvent * e);

如果返回值是true 代表用户处理这个事件,不向下分发了

QPainter

基本操作

1.在头文件声明函数

cpp 复制代码
    //绘图事件
    void paintEvent(QPaintEvent * );

2.在源文件实现函数

记得要引入类#include <QPainter>

cpp 复制代码
void Widget::paintEvent(QPaintEvent * )
{
    //实例化画家对象 this指定的是绘画设备
    QPainter painter(this);

    //设置画笔
    QPen pen(QColor(255,0,0));
    //设置画笔宽度
    pen.setWidth(3);
    //设置画笔风格
    pen.setStyle(Qt::DotLine);
    //让画家使用这支笔
    painter.setPen(pen);

    //设置画刷
    QBrush brush(Qt::cyan);
    //设置画刷风格
    painter.setBrush(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,60,60));

    //画文字
    painter.drawText(QRect(10,200,150,50),"好好学习,天天向上");
}

小结:
绘图事件 void paintEvent()
声明一个画家对象 QPainter painter(this) this指定绘图设备

画线、画圆、画矩形、画文字
设置画笔 QPen 设置画笔宽度 、风格
设置画刷 QBrush 设置画刷 风格

高级设置

抗锯齿

1.在头文件声明函数

cpp 复制代码
    //绘图事件
    void paintEvent(QPaintEvent * );

2.在源文件函数实现

cpp 复制代码
void Widget::paintEvent(QPaintEvent * )
{
    QPainter painter(this);
    painter.drawEllipse(QPoint(100,50),50,50);
    //设置 抗锯齿能力 效率较低
    painter.setRenderHint(QPainter::Antialiasing);
    painter.drawEllipse(QPoint(200,50),50,50);
}

移动坐标原点

cpp 复制代码
void Widget::paintEvent(QPaintEvent * )
{
    //画矩形
    painter.drawRect(QRect(20,20,50,50));
    //移动画家
    painter.translate(100,0);
    //保存画家状态
    painter.drawRect(QRect(20,20,50,50));
    painter.translate(100,0);

    //还原画家保存状态
    painter.drawRect(QRect(20,20,50,50));
}

画家画资源图片,并实现手动移动

1.导入资源图片

2.在ui界面设计一个按钮

3.在头文件声明函数和全局变量

cpp 复制代码
public:
    Widget(QWidget *parent = nullptr);
    ~Widget();
    //绘图事件
    void paintEvent(QPaintEvent * );
    int posX=0;

4.在源文件实现函数

cpp 复制代码
#include <QPainter>//画家

void Widget::paintEvent(QPaintEvent * )
{
    QPainter painter(this);
    //如果超出屏幕 从0开始
    if(posX>this->width())
    {
        posX=0;
    }
    painter.drawPixmap(posX,0,QPixmap(":/Image/Luffy.png"));
}

5.在源文件实现按钮

cpp 复制代码
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //点击移动按钮 移动图片
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        posX+=20;
        //如果要手动调用绘图事件 用update更新
        update();
    });
}

6.实现效果如下

小结:
抗锯齿 效率低

painter.setRenderHint(QPainter::Antialiasing);
对画家进行移动

painter.translate(100,0);
保存状态 save
还原状态 restore
如果想手动调用绘图事件 利用update
利用画家画图片 painter.drawPixmap( x,y,QPixmap( 路飞) )

作业

实现路飞的自动移动,即自动连播。

头文件

cpp 复制代码
#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 * );
    int posX=0;

private:
    Ui::Widget *ui;
};
#endif // WIDGET_H

源文件

cpp 复制代码
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>//画家
#include <QTimer>

Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    QTimer * timer = new QTimer(this);
    timer->start(500);

    connect(timer,&QTimer::timeout,[=](){
        posX+=20;
        update();
    });
}

void Widget::paintEvent(QPaintEvent * )
{
    QPainter painter(this);
    if(posX>this->width())
    {
        posX=0;
    }
    painter.drawPixmap(posX,0,QPixmap(":/Image/Luffy.png"));
}

Widget::~Widget()
{
    delete ui;
}

QPaintDevice绘图设备

QPixmap

对不同平台做了显示的优化

QPixmap pix( 300,300)

pix.fill( 填充颜色 )
利用画家 往pix上画画 QPainter painter( & pix)
保存 pix.save( "路径")

Qimage

可以对像素进行访问

使用和QPixmap差不多 QImage img(300,300,QImage::Format_RGB32);

其他流程和QPixmap一样
可以对像素进行修改 img.setPixel(i,j,value);

QPicture

记录和重现 绘图指令

QPicture pic

painter.begin(&pic);
保存 pic.save( 任意后缀名 )
重现 利用画家可以重现painter.drawPicture(0,0,pic);

QFile文件读写操作

1.在ui文件创建如下页面

2.文件为utf-8文件,进行读操作

添加头文件#include <QFileDialog> #include <QFile>

cpp 复制代码
    //点击选取文件按钮,弹出文件对话框
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\Gemini\\Desktop\\Qt-学习\\QT资料\\day3资料\\Doc");
        //将路径放入到lineEdit中
        ui->lineEdit->setText(path);

        //读取内容 放入到 textEdit中
        QFile file(path);  //参数是读取文件的路径
        //设置打开方式
        file.open(QIODevice::ReadOnly);

        //QByteArray array = file.readAll();两种读结果都一样
        QByteArray array;
        while(!file.atEnd())
        {
            array+=file.readLine();//按行读   
        }
        //将读取到的数据放入textEdit中
        ui->textEdit->setText(array);
        //对文件对象进行关闭
        file.close();
    });

3.进行写操作

cpp 复制代码
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\Gemini\\Desktop\\Qt-学习\\QT资料\\day3资料\\Doc");
        //将路径放入到lineEdit中
        ui->lineEdit->setText(path);

        //读取内容 放入到 textEdit中
        QFile file(path);  //参数是读取文件的路径
        
        //进行写操作
        file.open(QIODevice::Append);//用追加方式去进行写
        file.write("啊啊啊啊");
        file.close();
}

4.读写结合如下

QFileInfo文件信息获取

添加头文件include <QFileInfo>

在源代码

cpp 复制代码
    connect(ui->pushButton,&QPushButton::clicked,[=](){
        QString path = QFileDialog::getOpenFileName(this,"打开文件","C:\\Users\\Gemini\\Desktop\\Qt-学习\\QT资料\\day3资料\\Doc");
        //将路径放入到lineEdit中
        ui->lineEdit->setText(path);
        QFileInfo info(path);
        qDebug()<<"大小:"<<info.size()<<"后缀名"<<info.suffix()<<"文件名称:"<<info.fileName()<<"文件路径:"<<info.filePath();
        qDebug()<<"创建日期:"<<info.birthTime().toString("yyyy/MM/dd hh:mm:ss");
        qDebug()<<"最后修改日期"<<info.lastModified().toString("yyyy/MM/dd hh:mm:ss");
	}
相关推荐
zaim12 小时前
计算机的错误计算(一百一十四)
java·c++·python·rust·go·c·多项式
学习使我变快乐2 小时前
C++:const成员
开发语言·c++
500了3 小时前
Kotlin基本知识
android·开发语言·kotlin
Мартин.4 小时前
[Meachines] [Easy] Sea WonderCMS-XSS-RCE+System Monitor 命令注入
前端·xss
一律清风5 小时前
QT-文件创建时间修改器
c++·qt
不知所云,5 小时前
qt cmake自定义资源目录,手动加载资源(图片, qss文件)
开发语言·qt
昨天;明天。今天。5 小时前
案例-表白墙简单实现
前端·javascript·css
数云界5 小时前
如何在 DAX 中计算多个周期的移动平均线
java·服务器·前端
风清扬_jd5 小时前
Chromium 如何定义一个chrome.settingsPrivate接口给前端调用c++
前端·c++·chrome
安冬的码畜日常5 小时前
【玩转 JS 函数式编程_006】2.2 小试牛刀:用函数式编程(FP)实现事件只触发一次
开发语言·前端·javascript·函数式编程·tdd·fp·jasmine