1. 前言

前两篇博客简单的阐述了一下Qt的入门用法,这篇博客继续跟着视频学习。

Qt入门系列:
Qt学习之C++基础
Qt学习之Qt安装
Qt学习之Qt基础入门(上)
Qt学习之Qt基础入门(中)
Qt学习之Qt基础入门(下)

本文原创,创作不易,转载请注明!!!
本文链接
个人博客: https://ronglin.fun/archives/222
PDF链接:见博客网站
CSDN: https://blog.csdn.net/RongLin02/article/details/120668605

2. 自定义控件封装

有时候,我们希望一个控件是我们自己的设计的,比如将一个Label和进度条结合起来作为一个整体来使用
我们将一个Widget面板中加入自己设计好的控件,然后将面板作为 一个整体插入总ui中。
一个自定义功能:
设计两个按钮,为 开启–关闭 互补 状态,当点击开始按钮时,关闭按钮可用,开始按钮不可点击,当点击关闭按钮时,开启按钮可用,关闭按钮不可点击

2.1. 创建一个ui


然后就是选择基类,因为我们是在Widget面板上进行自定义,所以就选择Widget
然后就是自定义的类,取名叫做SwitchButtonWidget

然后下一步,完成就行了
之后会生成三个文件,一个是ui文件,然后就是类的.h .cpp文件。
我们先在ui界面设计控件,我这里就是两个按键,然后用了垂直布局,同时调整Widget面板大小

然后就在类中设计其逻辑功能,当点击开始按钮时,关闭按钮变成可用,开始按钮变得不可点击,当点击关闭按钮时,状态相反。
在文件switchbuttonwidget.cpp

#include "switchbuttonwidget.h"
#include "ui_switchbuttonwidget.h"SwitchButtonWidget::SwitchButtonWidget(QWidget *parent) :QWidget(parent),ui(new Ui::SwitchButtonWidget)
{ui->setupUi(this);ui->pushButton_2->setEnabled(false); //关闭按钮默认不可用//当点击开始按钮的时候connect(ui->pushButton,&QPushButton::clicked,[=](){ui->pushButton->setEnabled(false);   //关闭按钮设置可用ui->pushButton_2->setEnabled(true);  //开始按钮设置不可用});//当点击关闭按钮的时候connect(ui->pushButton_2,&QPushButton::clicked,[=](){ui->pushButton->setEnabled(true);   //关闭按钮设置不可用ui->pushButton_2->setEnabled(false);  //开始按钮设置可用});
}SwitchButtonWidget::~SwitchButtonWidget()
{delete ui;
}

到此,自定义的控件设计完毕

2.2. 运用自定义控件

设计完毕,就要在主ui中应用控件
因为我们的自定义控件的基类是Widget,所以我们在主ui中,拖入一个Widget面板,作为我们自定义框架的区域
然后 右键 -> 提升为

然后我们将这个普通的widget提升为我们自己自定义的控件面板,所以说提升的类名称就是刚才定义好的SwitchButtonWidget类,这里注意大小写,.h文件全是小写的,而类名是大小写都有的,然后全局包含,全局包含勾选的话就是以后用到这个自定义控件的时候可以直接使用,因为我们这里只用一次,就不勾选了

然后,点击 添加 ,然后点击 提升
之后虽然在ui中看不出来,但是在右侧,widget类已经变成SwitchButtonWidget类了,这就说明已经提升成功,运行查看结果

效果和预期一样,应用成功,只有一点不太方便的是,当提升之后,主ui中只是显示一个框框,不显示自定义控件的内容

3. Qt中的事件

事件和Java中类似,当用户对程序互交的时候,就会产生很多事件,例如点击鼠标,键盘输入,改变窗口大小等等

3.1. 鼠标事件

鼠标进入事件 enterEvent
鼠标离开事件 leaveEvent
鼠标按下 mousePressEvent ( QMouseEvent event)
鼠标释放 mouseReleaseEvent
鼠标移动 mouseMoveEvent
设置鼠标追踪方法:setMouseTracking(true);
同时在事件中封装了事件的状态,比如获取鼠标移动的坐标

event->x();    //x坐标
event->y();     //y坐标

而且也可以判断左右键,比如

if(event->button() == Qt::LeftButton)
{qDebug() << "点击了鼠标左键";
}
else if(event->button() == Qt::RightButton)
{qDebug() << "点击了鼠标右键";
}

同时,还有一个buttons方法可以同时判断多个,用法稍有不同

if(event->buttons() & Qt::LeftButton )
{qDebug() << "点击了鼠标左键";
}

可以用event->buttons()判断组合按键 判断move时候的左右键,要结合 & 操作符

小tips:
格式化字符串用法:QString( "%1 %2 ").arg( 111 ).arg(222);

3.2. event事件

在一些常用事件的上边还有一个层event事件,实现事件分发,返回值是bool,如果返回是true就代表用户要处理这个事件,不在向下分发。
函数原型是

bool event( QEvent * ev);

主要用于事件的分发,也可以做拦截操作,但是不建议,用法如下:

bool MyWidget::event(QEvent *e)
{//如果是鼠标按下 ,在event事件分发中做拦截操作if(e->type() == QEvent::MouseButtonPress){QMouseEvent * ev  = static_cast<QMouseEvent *>(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);
}

事件过滤器
同时在event之上还有一个事件过滤器,也可以做拦截,要重写eventfilter函数
在程序将时间分发到事件分发器前,可以利用过滤器做拦截
步骤
1、给控件安装事件过滤器

ui->label->installEventFilter(this);

2、重写 eventFilter函数 (obj , ev)

bool MyWidget::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);
}

关系如下图:

4. 定时器

定时器是一个很常用的用法,比如3s后关闭窗口等等
定时器有两种用法

4.1. 时间事件

3.1 利用事件 void timerEvent ( QTimerEvent * ev)
3.2 启动定时器 startTimer( 1000) 毫秒单位
3.3 timerEvent 的返回值是定时器的唯一标示 可以和ev->timerId 做比较

用法如下:
在.h文件的public下,先定义要重写定时器的事件,然后如果要有多个定时器,也要指定标识,例如这里有两个

public:explicit Widget(QWidget *parent = 0);~Widget();//重写定时器的事件void timerEvent(QTimerEvent *);int id1; //定时器1的唯一标示int id2; //定时器2的唯一标示

然后在.cpp文件中,先初始化定时器标识,比如是要1s还是2s,然后在timerEvent中判断即可

#include "widget.h"
#include "ui_widget.h"
#include <QDebug>
Widget::Widget(QWidget *parent) :QWidget(parent),ui(new Ui::Widget)
{ui->setupUi(this);//启动定时器id1 = startTimer(1000); //参数1  间隔  单位 毫秒id2 = startTimer(2000);
}void Widget::timerEvent(QTimerEvent * ev)
{if(ev->timerId() == id1){static int num = 1;//label2 每隔1秒+1ui->label_2->setText(  QString::number(num++));}if(ev->timerId() == id2){//label3  每隔2秒 +1static int num2 = 1;ui->label_3->setText(  QString::number(num2++));}
}Widget::~Widget()
{delete ui;
}

4.2. QTimer

只在一个事件中写多个定时器实在不方便,所以Qt提供了一个QTimer定时器类
利用定时器类 QTimer
创建定时器对象 QTimer * timer = new QTimer(this)
启动定时器 timer->start(毫秒)
每隔一定毫秒,发送信号 timeout ,进行监听
暂停 timer->stop
用法如下,用connect函数,当定时器到时间时要执行的操作

    //定时器第二种方式QTimer * timer = new QTimer(this);//启动定时器timer->start(500);connect(timer,&QTimer::timeout,[=](){static int num = 1;//label4 每隔0.5秒+1ui->label_4->setText(QString::number(num++));});//点击暂停按钮 实现停止定时器connect(ui->btn,&QPushButton::clicked,[=](){timer->stop();});

5. 画图

5.1. QPainter 绘图

绘图事件 void paintEvent()
声明一个画家对象 QPainter painter(this) this指定绘图设备
可以画线、画圆、画矩形、画文字
设置画笔 QPen 设置画笔宽度 、风格,设置画刷 QBrush 设置画刷 风格
直接看代码用法,需要注意的时,如果需要重画的时候,调用update();即可,就能重画paintEvent内的内容
有关具体 用法可查询API

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);//设置画刷风格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,150,50) , "好好学习,天天向上");    //画文字}

5.2. QPainter高级设置

抗锯齿 效率低

painter.setRenderHint(QPainter::Antialiasing);

对画家进行移动
painter.translate(100,0);
保存状态 save
还原状态 restore
如果想手动调用绘图事件 利用update
利用画家画图片 painter.drawPixmap( x,y,QPixmap( 路飞) )
用法见下,不再仔细说明

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);画矩形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(":/Image/Luffy.png");
//    //如果超出屏幕 从0开始
//     if(posX >= this->width())
//     {
//         posX = -pix.width();
//     }
//     painter.drawPixmap(posX,0,pix);}

5.3. QPaintDevice绘图设备

QPixmap QImage QBitmap(黑白色) QPicture QWidget
有关绘图设备这里不过多说明,API中有详细的说明

5.3.1. QPixmap

QPixmap 对不同平台做了显示的优化
QPixmap pix( 300,300) pix.fill( 填充颜色 )
利用画家 往pix上画画 QPainter painter( & pix)
保存 pix.save( “路径”)

5.3.2. Qimage

Qimage 可以对像素进行访问
使用和QPixmap差不多 QImage img(300,300,QImage::Format_RGB32);
其他流程和QPixmap一样
可以对像素进行修改 img.setPixel(i,j,value);

5.3.3. QPicture

QPicture 记录和重现 绘图指令
QPicture pic
painter.begin(&pic);
保存 pic.save( 任意后缀名 )
重现 利用画家可以重现painter.drawPicture(0,0,pic);

6. 文件操作

文件操作十分常见了,Qt的文件操作和C++的类似,十分简便,不像Java文件操作复杂

6.1. QFile

对文件进行读写操作
QFile进行读写操作
QFile file( path 文件路径)

6.1.1. 读

file.open(打开方式) QIODevice::readOnly
全部读取 file.readAll() 按行读 file.readLine() atend()判断是否读到文件尾
认支持编码格式 utf-8
利用编码格式类 指定格式 QTextCodeC
QTextCodec * codec = QTextCodec::codecForName(“gbk”);
//ui->textEdit->setText( codec->toUnicode(array) );
文件对象关闭 close

6.1.2. 写

file.open( QIODevice::writeOnly / Append)
file.write(内容)
file.close 关闭

6.2. QFileInfo

读取文件信息
QFileInfo info(路径)
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”);

用法

#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#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,"打开文件","C:\\Users\\Desktop");//将路径放入到lineEdit中ui->lineEdit->setText(path);//编码格式类//QTextCodec * codec = QTextCodec::codecForName("gbk");//读取内容 放入到 textEdit中// QFile默认支持的格式是 utf-8QFile file(path); //参数就是读取文件的路径//设置打开方式file.open(QIODevice::ReadOnly);//QByteArray array = file.readAll();QByteArray array;while( !file.atEnd()){array += file.readLine(); //按行读}//将读取到的数据 放入textEdit中ui->textEdit->setText(array);//ui->textEdit->setText( codec->toUnicode(array)  );//对文件对象进行关闭file.close();//进行写文件
//        file.open(QIODevice::Append); //用追加方式进行写
//        file.write("啊啊啊啊啊");
//        file.close();//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");});}Widget::~Widget()
{delete ui;
}

7. 总结

至此,Qt基础入门结束,跟着视频学也挺好的,=w=

Qt学习之Qt基础入门(下)相关推荐

  1. Qt学习之Qt基础入门(中)

    1. 前言 上一篇博客,总结了Qt的一些基础用法,这篇博客继续跟视频学习Qt的常用方法 Qt入门系列: Qt学习之C++基础 Qt学习之Qt安装 Qt学习之Qt基础入门(上) Qt学习之Qt基础入门( ...

  2. 阿里云天池学习赛-零基础入门数据分析-学术前沿趋势分析(task1)

    阿里云天池学习赛零基础入门数据分析-学术前沿趋势分析 前言 一.赛题描述及数据说明 1:数据集的格式如下: 2:数据集格式举例: 二.task1论文数量统计(数据统计任务):统计2019年全年,计算机 ...

  3. 1、Latex学习笔记之基础入门篇

    目录 一.Latex基础 1.架构 2.引用.脚注 3.单栏.双栏 4.常用快捷键 5.宏包 6.空格 7.换行.行间距 8.换段 9.下划线 10.引号 11.注释 12.字体 13.缩进 14.超 ...

  4. 视频教程-人人都会深度学习之Tensorflow基础入门-深度学习

    人人都会深度学习之Tensorflow基础入门 大数据工程师/算法工程师/大数据讲师,毕业于西华大学软件工程专业.在大数据领域有着丰富的实战经验. 擅长领域:Spark/Hadoop.算法设计及系统架 ...

  5. Spark大数据开发学习:Spark基础入门

    在诸多的大数据技术框架当中,Spark可以说是占据了非常重要的地位,继Hadoop之后,基于实时数据处理需求的不断上升,Spark开始占据越来越大的市场份额,而Spark,也成为大数据的必学知识点.今 ...

  6. 【Qt Quick】零基础入门系列之安装与卸载(一)

    [Qt Quick]概述 |本文大概阅读时间8分钟. |版权说明:原创文章,如需转载,请标明文章出处.https://blog.csdn.net/weixin_40192195/article/det ...

  7. C++后续:QT学习(Qt概述,创建QT项目)

    目录 声明 一. Qt概述 1.1 什么是Qt 1.2 Qt的发展史 1.3 Qt支持的平台 1.4 Qt版本 1.5 Qt的下载与安装 1.6 Qt的优点 二.创建 Qt项目 2.1 如何创建 2. ...

  8. Qt 学习(三) —— Qt 模块

    1. Qt 模块简介 Qt由许多模块组成,分别支持不同领域的功能,主要分为 Essentials 和 Add-On. Qt Essential 是基本模块,它们可以在所有受支持的开发平台和经过测试的目 ...

  9. 嵌入式学习之QT学习---14 QT跨平台运行之把QT程序交叉编译到ARM开发板

    想要把qt工程放到开发板上运行,就需要用到交叉编译.由于qt是跨平台的,所以只需要换个编译器编译一下就可以. 以qt学习–计时器的例子为例,在移植之前还需要进行一个准备工作,在windows下运行的时 ...

最新文章

  1. label实现不同大小不同颜色
  2. Thrift解读(五)——server端RPC接收与返回值的回送
  3. xaml中的布局面板
  4. 【UOJ188】 Sanrd【类min_25筛】
  5. html用转义字符画菱形,JavaScript生成字符画(ASCII Art)
  6. Redis:缓存问题之数据不一致(更新数据库时 主动更新)
  7. JavaMail---简介
  8. linux date -d 的一些使用方法
  9. 6.1离散时间马尔科夫链
  10. Alpine Linux如何安装软件
  11. soapui使用教程1-基本使用和录制
  12. springboot activiti 7 和activiti 6 配置详解
  13. 《麦肯锡方法》第7章 进行研究-思维导图
  14. Github emoji 表情包大全
  15. 做跨境如何去降低成本?
  16. 使用Feurio刻录音乐CD 无损音乐FLAC
  17. 卓文萱在北京净万家像街头卖艺似的骗子粉丝做公益绯闻男友辰亦儒看不惯假惺惺模样破口大骂
  18. 阿里云服务器租用价格最新收费标准(2019实时更新)
  19. 闲谈IPv6-Anycast以及在Linux/Win7系统上的Anycast配置
  20. 用户画像-数据指标体系划分

热门文章

  1. OrderOnline——设计概述
  2. 网络管理命令ping和arping
  3. 设计模式 之 桥接模式
  4. 程序员经典面试题,高并发系统,一般需要怎么做
  5. BI报表平台纪实:半年被叫停,用户个位数,分析后我找到了原因
  6. 我写过最长的东西可能就是高考作文了
  7. 今天的成功的滋味 企业即时通讯
  8. 飞鸽传书,去看了下WEBBROWSER的资料
  9. 一个值得收藏的小工具
  10. 经典面试题(7):下面的代码运行结果是什么么?