Qt学习笔记-DAY3
1.自定义控件封
窗口中的某个模块会被经常性的重复使用。一般遇到这种情况我们都会将这个窗口或者模块拿出来做成一个独立的窗口类,以备以后重复使用。
例如:我们从QWidget派生出一个类SmallWidget,实现了一个自定窗口
step1.添加新文件—Qt 设计师界面类
Qt 设计师界面类包含.h .cpp .ui
step2.ui中 设计 QSpinBox和QSlider 两个控件
实现功能:改变数字,滑动条跟着移动
step3.在主Widget中提升为
加入一个空窗口 提升为
step4.功能实现
在.h文件 声明 get、set接口
#ifndef SMALLWIDGET_H
#define SMALLWIDGET_H
#include <QWidget>
namespace Ui {
class SmallWidget;
}
class SmallWidget : public QWidget
{
Q_OBJECT
public:
explicit SmallWidget(QWidget *parent = 0);
~SmallWidget();
//设置数字
void setNum(int num);
//获取数字
int getNum();
private:
Ui::SmallWidget *ui;
};
#endif // SMALLWIDGET_H
在.cpp中实现 控件的关联、set、get函数
#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);
}
//设置数字
void SmallWidget::setNum(int num)
{
ui->spinBox->setValue(num);
}
//获取数字
int SmallWidget::getNum()
{
return ui->spinBox->value();
}
SmallWidget::~SmallWidget()
{
delete ui;
}
2.Qt中的事件
2.1.1.鼠标事件
虚函数 可以被各个子类继承后 按需重写
在.h中申明 鼠标事件(5种)
//鼠标进入事件
void enterEvent(QEvent *event);
//鼠标离开事件
void leaveEvent(QEvent *);
//鼠标按下
virtual void mousePressEvent(QMouseEvent *ev);
//鼠标释放
virtual void mouseReleaseEvent(QMouseEvent *ev);
//鼠标移动
virtual void mouseMoveEvent(QMouseEvent *ev);
在.cpp重写虚函数-----实现需求
#include "mylabel.h"
#include <QDebug>
#include <QMouseEvent>
//鼠标进入事件
void myLabel::enterEvent(QEvent *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;
}
}
2.1.2.传入参数QMouseEvent
可用于判断左右键、鼠标坐标
ev->x() x坐标 ev->y() y坐标
ev->button() 可以判断所有按键 Qt::LeftButton Qt::RightButton
ev->buttons() 判断组合按键 判断move时候的左右键 结合 &位与 操作符
2.1.3.设置鼠标追踪
在构造函数加setMouseTracking(true);则鼠标移动时无需按下鼠标
3.定时器
3.1.实现方法一(不推荐)
①.h中添加事件 void timerEvent ( QTimerEvent * ev)
#ifndef WIDGET_H
#define WIDGET_H
#include <QWidget>
namespace Ui {
class Widget;
}
class Widget : public QWidget
{
Q_OBJECT
public:
explicit Widget(QWidget *parent = 0);
~Widget();
//重写定时器的事件
void timerEvent(QTimerEvent *);
int id1; //定时器1的唯一标示
int id2; //定时器2的唯一标示
private:
Ui::Widget *ui;
};
#endif // WIDGET_H
②启动定时器 startTimer( 1000) 毫秒单位
如需要多个定时timerEvent 的返回值是定时器的唯一标示 可以和ev->timerId 做比较
注意定时时间 变量 要定义为 static int
#include "widget.h"
#include "ui_widget.h"
#include <QTimer> //定时器类
#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)
{
//label2 每隔1秒+1
static int num = 1;
ui->label_2->setText( QString::number(num++));
}
if(ev->timerId() == id2)
{
//label3 每隔2秒 +1
static int num2 = 1;
ui->label_3->setText( QString::number(num2++));
}
}
3.2.实现方法二(强推)
想有多个计时器就创建多个QTimer * timer 即可
timer->stop()可停止计时
原理:每隔一定毫秒,发送信号 timeout ,进行监听
#include "widget.h"
#include "ui_widget.h"
#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,[=](){
static int num = 1;
//label4 每隔0.5秒+1
ui->label_4->setText(QString::number(num++));
});
}
4.Qt绘图
我们可以把**QPainter**理解成画笔;把**QPaintDevice**理解成使用画笔的地方
绘图设备是指继承QPainterDevice的子类
Qt一共提供了4+1个子类:QPixmap、QBitmap、QImage、QPicture
Qwidget 也为 Qpaintdevice子类 也是个绘图设备
虚函数——void paintEvent(QPaintEvent *) 会自动 调用,不用在手动调用
4.1.Qwidget 为绘图设备
step1.在Widget.h里创建绘图event
public:
explicit Widget(QWidget *parent = 0);
~Widget();
//绘图事件--打( 按tab键自动补全 参数
void paintEvent(QPaintEvent *);
step2.在Widget.cpp里实现paintEvent()
#include "widget.h"
#include "ui_widget.h"
#include <QPainter> //画家类
//实例化画家对象 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)); //从(20,20)画50*50矩阵
//画文字
painter.drawText(QRect(10,200,150,50) , "好好学习,天天向上");
step3.QPainter高级设置
抗锯齿 | 移动画家 | 保存画家状态 | 还原画家状态(上一个保存点) |
---|---|---|---|
painter.setRenderHint(QPainter::Antialiasing) | painter.translate(100,0) | painter.save() | painter.restore() |
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));
例子:利用画家画图片
点击移动按钮,移动图片
手动调用绘图事件 | 利用画家画图片 |
---|---|
利用update() | painter.drawPixmap( x,y,QPixmap(“:路径”) ) |
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
//点击移动按钮,移动图片
connect(ui->pushButton,&QPushButton::clicked,[=](){
posX+=20;
//如果要手动调用绘图事件 用update更新
update();
});
}
void Widget::paintEvent(QPaintEvent *)
{
//**************利用画家 画资源图片**************//
QPainter painter(this);
QPixmap pix = QPixmap(":/Image/Luffy.png");
//如果超出屏幕 从0开始
if(posX >= this->width())
{
posX = -pix.width();
}
painter.drawPixmap(posX,0,pix);
}
4.2.QBitmap为绘图设备
QBitmap是QPixmap的一个子类,它用于画黑白图,可以使用
QPixmap的isQBitmap()函数来确定这个QPixmap是不是一个QBitmap
void PaintWidget::paintEvent(QPaintEvent *)
{
QPixmap pixmap(":/Image/butterfly.png");
QPixmap pixmap1(":/Image/butterfly1.png");
QBitmap bitmap(":/Image/butterfly.png");
QBitmap bitmap1(":/Image/butterfly1.png");
QPainter painter(this);
painter.drawPixmap(0, 0, pixmap);
painter.drawPixmap(200, 0, pixmap1);
painter.drawPixmap(0, 130, bitmap);
painter.drawPixmap(200, 130, bitmap1);
}
4.3.QPixmap为绘图设备
对不同平台做了显示的优化
#include "widget.h"
#include "ui_widget.h"
#include <QPixmap>
#include <QPainter>
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); //指定画布 (上面都写this)
painter.setPen(QPen(Qt::green));
painter.drawEllipse(QPoint(150,150) , 100,100);
//保存
pix.save("E:\\pix.png");
}
4.4.QImage为绘图设备
可以对像素进行访问
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QImage>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
//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);
}
4.5.QPicture为绘图设备
记录和重现 绘图指令
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QPicture>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
//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.hxy");
}
//************在paintEvent中 重现**************//
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
//重现QPicture的绘图指令
QPicture pic;
pic.load("E:\\pic.hxy");
painter.drawPicture(0,0,pic);
}
5.文件IO
5.1.QFile 对文件进行读写操作
例子:
5.1.1.读
#include "widget.h"
#include "ui_widget.h"
#include <QFileDialog>
#include <QFile>
#include <QTextCodec>
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\\zhangtao\\Desktop");
//将路径放入到lineEdit中
ui->lineEdit->setText(path);
//*************读取内容 放入到 textEdit中*******//
//**step1:创建QFile 对象
QFile file(path); //参数就是读取文件的路径
//**step2:设置打开方式——读,写
file.open(QIODevice::ReadOnly);
//**step3:读取文件
//1.全部读取
//QByteArray array = file.readAll();
//2.按行读
QByteArray array;
while( !file.atEnd())
{
array += file.readLine();
}
//**step4:将读取到的数据 放入textEdit中
//1.utf-8 格式直接放
ui->textEdit->setText(array);
//2.其他格式转
// QFile默认支持的格式是 utf-8
//QTextCodec * codec = QTextCodec::codecForName("gbk"); //编码格式类
//ui->textEdit->setText( codec->toUnicode(array) );
//**step5:对文件对象进行关闭
file.close();
});
}
5.1.2.写
//进行写文件
file.open(QIODevice::Append); //用追加方式进行写
file.write("啊啊啊啊啊");
file.close();
5.2.QFileInfo 读取文件信息
#include "widget.h"
#include "ui_widget.h"
#include <QFile>
#include <QFileInfo>
#include <QDebug>
#include <QDateTime>
//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");