目录
一、封装自定义控件
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_QtFventhttps://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_QPainterhttps://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_QtPaintDevicehttps://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_Qtfilehttps://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");
});
结果图:
第三天的学习记录分享完毕,关注我,带你了解更多的编程知识。
看到这里,不妨点个攒,关注一下吧!
最后,谢谢你的观看!