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

news2025/4/5 10:42:12

文章目录

  • 自定义控件封装
  • 自定义框架
  • 定时器
    • 第一种方式
    • 第二种方式 (推荐)
  • 事件分发器
  • QPainter
    • 基本操作
    • 高级设置
      • 抗锯齿
      • 移动坐标原点
    • 画家画资源图片,并实现手动移动
  • 作业
  • QPaintDevice绘图设备
    • QPixmap
    • Qimage
    • QPicture
  • QFile文件读写操作
    • QFileInfo文件信息获取

自定义控件封装

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中实现这两个函数
在这里插入图片描述
6.

自定义框架

1.创建新文件-C/C+±Class,我这里命名为myLable.
在这里插入图片描述
在这里插入图片描述
2.改3处类名
在这里插入图片描述
在这里插入图片描述

3.在头文件写函数声明

    //鼠标进入事件
    void enterEvent(QEnterEvent *event);
    //鼠标离开事件
    void leaveEvent(QEvent *);

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

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

在这里插入图片描述
4.在源文件实现函数

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个公有变量

public:
    Widget(QWidget *parent = nullptr);
    ~Widget();

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

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


private:
    Ui::Widget *ui;
};

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

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.在头文件添加函数声明

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

在这里插入图片描述

2.在源文件实现函数

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.在头文件声明函数

    //绘图事件
    void paintEvent(QPaintEvent * );

在这里插入图片描述
2.在源文件实现函数

记得要引入类#include <QPainter>

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.在头文件声明函数

    //绘图事件
    void paintEvent(QPaintEvent * );

2.在源文件函数实现

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);
}

移动坐标原点

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.在头文件声明函数和全局变量

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

4.在源文件实现函数

#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.在源文件实现按钮

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( 路飞) )

作业

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

头文件

#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

源文件

#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>

    //点击选取文件按钮,弹出文件对话框
    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.进行写操作

    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>

在源代码

    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");
	}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1902518.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

FPGA_GTX:简要版

1. GTX介绍 Xilinx FPGA的GT意思是Gigabyte Transceiver。通常称呼为Serdes、高速收发器。GT在xilinx不同系列有着不同的产品&#xff0c;从7系列到UltraScale系列分别有GTP、GTX、GTZ、GTH、GTY和GTM。不同GT整体结构上类似&#xff0c;为了支持越来越高的line rate&#xff…

virtualbox窗口和win10窗口的切换

1、问题&#xff1a; 从windows切换到虚拟机可以用快捷键 ALTTAB&#xff0c;但是从虚拟机到windows使用 ALTTAB 无法成功切换 2、解决方法&#xff1a; 注意&#xff1a;发现设置为ctrlAlt会导致打开终端快捷键&#xff08;CtrlAltT&#xff09;失效&#xff0c;建议这里设置…

Lua语言入门

目录 Lua语言1 搭建Lua开发环境1.1 安装Lua解释器WindowsLinux 1.2 IntelliJ安装Lua插件在线安装本地安装 2 Lua语法2.1 数据类型2.2 变量全局变量局部变量命名规范局部变量作用域 2.3 注释单行注释多行注释 2.4 赋值2.5 操作符数学操作符比较操作符逻辑操作符连接操作符取长度…

HACCP体系认证:守护食品安全的黄金标准

在食品生产过程中&#xff0c;食品安全始终是重中之重。为了确保食品的安全性和质量&#xff0c;越来越多的企业开始采用HACCP&#xff08;危害分析关键控制点&#xff09;体系认证。这个体系不仅能帮助企业预防食品安全问题&#xff0c;还能显著提升产品质量和市场竞争力。 HA…

深入探索C语言中的结构体:定义、特性与应用

&#x1f525; 个人主页&#xff1a;大耳朵土土垚 目录 结构体的介绍结构体定义结构成员的类型结构体变量的定义和初始化结构体成员的访问结构体传参 结构体的介绍 在C语言中&#xff0c;结构体是一种用户自定义的数据类型&#xff0c;它允许开发者将不同类型的变量组合在一起…

适用于Mac和Windows的最佳iPhone恢复软件

本文将指导您选择一款出色的iPhone数据恢复软件来检索您的宝贵数据。 市场上有许多所谓的iPhone恢复程序。各种程序很难选择并选择其中之一。一旦您做出了错误的选择&#xff0c;您的数据就会有风险。 最好的iPhone数据恢复软件应包含以下功能。 1.安全可靠。 2.恢复成功率高…

郭明錤:苹果将为Vision Pro推出红外摄像头款AirPods

在科技界,苹果公司的每一次创新都备受瞩目。近日,著名苹果分析师郭明錤透露了一个令人振奋的消息:苹果计划在2026年推出配备红外摄像头的新款AirPods,这款耳机将特别优化与Apple Vision Pro头显的空间体验。这一消息不仅预示着苹果在音频设备领域的又一次技术飞跃,也进一步…

One day for Chinese families

周围生活中的普通家庭的一天流程&#xff1a; 【上班的一天】 【放假的一天】 有家庭的人&#xff0c;上班流程&#xff1a; 01&#xff09;准备早餐&#xff0c;牛奶&#xff0c;面包 02&#xff09;叫娃娃起床&#xff0c;一般要蛮久的&#xff1b;沟通交流 -- 哄娃娃 -- 生气…

【Linux进阶】文件系统8——硬链接和符号连接:ln

在Linux下面的链接文件有两种&#xff0c; 一种是类似Windows的快捷方式功能的文件&#xff0c;可以让你快速地链接到目标文件&#xff08;或目录)&#xff1b;另一种则是通过文件系统的inode 链接来产生新文件名&#xff0c;而不是产生新文件&#xff0c;这种称为硬链接&…

html+css+js图片手动轮播

源代码在界面图片后面 轮播演示用的几张图片是Bing上的&#xff0c;直接用的几张图片的URL&#xff0c;谁加载可能需要等一下&#xff0c;现实中替换成自己的图片即可 关注一下点个赞吧&#x1f604; 谢谢大佬 界面图片 源代码 <!DOCTYPE html> <html lang&quo…

前端面试题9(JavaScript数组去重)

1. 使用Set ES6引入了Set数据结构&#xff0c;它只存储唯一的值&#xff0c;因此可以用来快速去重。 function uniqueWithSet(arr) {return [...new Set(arr)]; }// 示例 console.log(uniqueWithSet([1, 2, 2, 3, 4, 4, 5])); // 输出: [1, 2, 3, 4, 5]2. 使用indexOf或inclu…

Poker Game, Run Fast

Poker Game, Run Fast 扑克&#xff1a;跑得快 分门别类&#xff1a; 单张从小到大默认 A < 2 < 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 < J < Q < K 跑得快&#xff1a;单张从小到大 3 < 4 < 5 < 6 < 7 < 8 < 9 < 10 &…

第二次练习

目录 一、student表的增删改查 1.向student表中添加一条新记录 2. 向student表中添加多条新记录 3.向student表中添加一条新记录 4.更新表&#xff0c;grade 大于90的加0.5 5.删除成绩为空的记录 二、用户权限部分 1、创建一个用户test1使他只能本地登录拥有查询student表的权…

比赛获奖的武林秘籍:03 好的创意选取-获得国奖的最必要前提

比赛获奖的武林秘籍&#xff1a;03 好的创意选取-获得国奖的最必要前提 摘要 本文主要介绍了大学生电子计算机类比赛和创新创业类比赛创意选取的重要性&#xff0c;并列举了好的创意选取和坏的创意选取的例子&#xff0c;同时说明了好的创意选取具有哪些特点&#xff0c;同时…

当需要对大量数据进行排序操作时,怎样优化内存使用和性能?

文章目录 一、选择合适的排序算法1. 快速排序2. 归并排序3. 堆排序 二、数据结构优化1. 使用索引2. 压缩数据3. 分块排序 三、外部排序1. 多路归并排序 四、利用多核和并行计算1. 多线程排序2. 使用并行流 五、性能调优技巧1. 避免不必要的内存复制2. 缓存友好性3. 基准测试和性…

Qt(MSVC)下报“语法错误缺少“}““语法错误缺少“常数“ 的解决办法

1.现象 目前我在工程中试图使用QHttpServer时&#xff0c;一编译&#xff0c;就报了一堆奇奇怪怪的错误&#xff1a; D:\Qt\httpServer\Qt5.15.2\include\QtHttpServer\qhttpserverrequest.h:75: error: C2143: 语法错误: 缺少“}”(在“(”的前面) D:\Qt\httpServer\Qt5.15.…

最新扣子(Coze)实战案例:使用图像流做超分,模糊图片秒变清晰,完全免费教程

&#x1f9d9;‍♂️ 大家好&#xff0c;我是斜杠君&#xff0c;手把手教你搭建扣子AI应用。 &#x1f4dc; 本教程是《AI应用开发系列教程之扣子(Coze)实战教程》&#xff0c;完全免费学习。 &#x1f440; 关注斜杠君&#xff0c;可获取完整版教程。&#x1f44d;&#x1f3f…

Mysql中间件和高可用

文章目录 一、MySQL中间件代理服务器MycatMycat应用场景Mycat部署 实现读写分离 二、MySQL高可用高可用解决方案MHA高可用实现MHA 一、MySQL中间件代理服务器 数据库主要分为两大类&#xff1a;关系型数据库与 NoSQL 数据库&#xff08;非关系型数据库&#xff09;。 数据库主…

软考中级数据库系统工程师备考经验分享

前几天软考成绩出了&#xff0c;赶紧查询了一下发现自己顺利通过啦&#xff08;上午63&#xff0c;下午67&#xff0c;开心&#xff09;&#xff0c;因此本文记录一下我的备考经验分享给大家。因为工作中项目管理类的知识没有系统学习过&#xff0c;本来想直接报名软考高级证书…

7.6第三天作业

一、在数据库中创建一个表student&#xff0c;用于存储学生信息 CREATE TABLE student( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL, grade FLOAT ); &#xff08;1.&#xff09;先创建一个数据库 &#xff08;2.&#xff09;创建student表 查看是否创建成功 1、向studen…