qt – 图像
qt-图像操作
https://blog.csdn.net/iriczhao/article/details/123265538
https://blog.csdn.net/weixin_44116061/article/details/106412187!!!
https://blog.csdn.net/qq_45662588/article/details/120366824
- QPixmap
- QImage
- QBitmap
- QPicture
QPixmap
图片类,用于显示图片
对于图片的显示做了优化处理
在平台有关,不同平台在内部的存储形式有区别
只能在主线程中使用
QPixmap对象可以通过值传递
QPixmap中的像素是由操作系统管理的
Qpixmap 中的像素只能通过Qpainter或转换成QImage才能访问
读取/写入
load()/loadFromdata() // 从本地文件或资源文件中读取
save() // 保存qpixmap对象
构建/保存
// 相当于一个画布,不依赖与Widget
QPixmap pix(400,300); // 像素是400,300
pix.fill(Qt::white);
QPainter painter(&pix);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100,100),50,50);
pix.save("./mypix.jpg"); // 保存到本地磁盘
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this);
QPixmap pix;
pix.load("mypix.jpg");
painter.drawPixmap(0,0,50,50,pix); //在(0,0)点起始的宽高均为50的矩形中显示图片
painter.translate(50,50); //将起始点改为(50,50)
painter.drawPixmap(0,0,50,50,pix); //在(50,50)起始的宽高为50的矩形中显示图片
}
QLabel/QPixmap
QPixmap pix("/path");
QLabel label;
label.setPixmap(pix);
label.show();
QPushButton/QToolButton/QPixmap
可以基于QPixmap将图像显示到QPushButton/QToolButton
QPixmap/QImage
通常,QImage 类用于加载图像文件,并操作图像数据。然后将 QImage 对象转成 QPixmap 对象在屏幕上显示
如果不需要对像素进行操作,可以直接将图像加载到QPixmap中
QImage –> QPixmap
QPixmap::fromImage()
QPixmap –> QImage
QPixmap::toImage()
QPixmap/imageReader
fromImagereader
从直接从 imageReader 读取的图像创建 QPixmap
QPixmap/QByteArray
loadFromData
uchar* 或 QByteArray –> QPixmap
从直接从 imageReader 读取的图像创建 QPixmap
QPixmap/QDatastream/QFile
写入
将给定的像素图作为 PNG 图像写入给定的流。
注意,将流写入文件不会产生有效的图像文件
QFile file("file.dat");
QDataStream stream(&file);
file.open(QIODevice::WriteOnly);
QPixmap pixmap("D://eee.jpg");
stream << pixmap;
file.close();
读取
从给定的流中读取图像到给定的像素图
QFile file("file.dat");
file.open(QIODevice::ReadOnly);
QDataStream stream(&file);
QPixmap pixmap;
stream >> pixmap;
file.close();
QLabel label;
label.setPixmap(pixmap);
label.show();
QImage
图片类,不依赖于平台,任何平台在内部的存储形式都是一样的
可以用于多线程中
多用于图片的传输,可以做像素级的修改
I/O优化
读取/写入
load()/loadFromdata() // 从本地文件或资源文件中读取
save() // 保存qpixmap对象
加载/像素级修改
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QImage img;
img.load(":/images/images/bus.jpg");
for (int i=50;i<100;i++)
{
for (int j=50;j<100;j++)
{
img.setPixel(i,j,qRgb(255,0,0));
}
}
painter.drawImage(0,0,img);
}
QImage/QPainter
构建/保存
QImage img(400,300,QImage::Format_RGB32);
img.fill(Qt::white);
QPainter painter(&img);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100,100),50,50);
img.save("./myimg.jpg"); // 保存到本地磁盘
加载/像素级修改
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QImage img;
img.load(":/images/images/bus.jpg");
for (int i=50;i<100;i++)
{
for (int j=50;j<100;j++)
{
img.setPixel(i,j,qRgb(255,0,0));
}
}
painter.drawImage(0,0,img);
}
QImage/QLabel
最好的方式是转换为QPixmap显示到QLabel
QImage/QPixmap
见QPixmap/QImage
QImage/imageReader
QImage/QByteArray
QImage/QDatastream/QFile
QPicture
可以理解为一个绘图的工具,保存有绘图的记录(类比QPainterPath)和重绘制的指令
存储的形式是二进制形式
与QPainter联合使用,用于记录和回播Qpainter
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
QPicture pic;
// version1
// QPainter painter(&pic);
// painter.setPen(Qt::red);
// painter.drawEllipse(QPoint(100,100),50,50);
// painter.end();
// version2
QPainter painter;
painter.begin(&pic);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100,100),50,50);
painter.end();
// pic.save("./mypic.dat"); //二进制的形式
}
加载
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
QPicture pic;
pic.load("./mypic.dat");
painter.drawPicture(0,0,pic);
}
QBitmap
只能是黑白图像 不能是彩色图像
继承自QPixmap 深度为1
QBitmap bm(400,300);
QPainter painter(&bm);
painter.setPen(Qt::red);
painter.drawEllipse(QPoint(100,100),50,50);
bm.save("./bm.jpg");
QImageReader/QImageWriter
QPainter绘图
QPaintEvent
绘图事件 – >paintEvent
绘图事件处理函数
当发生QPaintEvent
绘图事件时,就自动调用paintEvent
绘图事件处理函数
对于
QPainterEvent
绘图事件处理函数,当程序运行后,窗体自动调用QPainterEvent
绘图事件处理函数
事件处理
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this); // 创建一个QPainter类对象 调用构造函数 this指针指向的是当前Widget这个窗体
painter.setPen(Qt::blue);
painter.setFont(QFont("Arial",30));
painter.drawText(rect(),Qt::AlignCenter,"Qt"); // rect表示在一个矩形的区域里绘制文字
// 绘制文字
QFont font("楷体",20,QFont::Bold,true); // 字体、字号、加速、斜体
font.setUnderline(true); // 设置下划线
painter.setFont(font);
painter.setPen(Qt::blue);
painter.drawText(50,50,"hello world"); // 50,50表示左上角坐标
// 指定使用绘图工具
QPen pen(QColor(255,0,0)); // 创建一个画笔
pen.setWidth(3); // 设置粗细
pen.setStyle(Qt::DashDotDotLine);
painter.setPen(pen); // 使用绘笔
// 画线
painter.drawLine(QPoint(0,0),QPoint(100,100)); // 创建QPoint的匿名对象
// 画圆
painter.drawEllipse(QPoint(100,100),20,20);
// 椭圆
painter.drawEllipse(QPoint(100,100),50,30);
// 矩形
painter.drawRect(100,100,30,50); // (100,100)是左上角的坐标
// 正方形
painter.drawRect(100,100,80,80);
// QPen 画笔
// QBrush 画刷
QBrush brush(Qt::green,Qt::Dense1Pattern);
painter.setBrush(brush);
// painter.setPen(pen); // 加不加setPen都行好像
painter.drawRect(200,200,80,80);
}
事件处理进阶
#include "widget.h"
#include "ui_widget.h"
#include <QPainter>
#include <QPen>
#include <QPoint>
#include <QTimer>
Widget::Widget(QWidget *parent) :
QWidget(parent),
ui(new Ui::Widget)
{
ui->setupUi(this);
angle=0;
// 创建定时器
QTimer *timer=new QTimer(this);
timer->start(1000);
// QWidget::update 会自动调用paintEvent函数!!!
void (QWidget:: *widget_update)()=&QWidget::update;
connect(timer,&QTimer::timeout,this,widget_update); // 因为存储在函数重载
// connect(timer,&QTimer::timeout,this,&QWidget::repaint);
}
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// 更新angle
angle+=10;
if (angle==360) angle=0;
// 抗锯齿
painter.setRenderHint(QPainter::Antialiasing);
// 将坐标系平移到当前窗体的中心,其始终是跟随状态
// this->width(),this->height()
painter.translate(this->width()/2,this->height()/2);
painter.drawEllipse(QPoint(0,0),120,120);
painter.rotate(angle);
painter.drawLine(QPoint(0,0),QPoint(100,0));
}
绘制设置
锥形渐变
void Widget::paintEvent(QPaintEvent *)
{
QPainter painter(this); // 创建一个QPainter类对象 调用构造函数 this指针指向的是当前Widget这个窗体
// 锥形渐变
// 默认逆时针旋转,0表示实际的三点钟方向
QConicalGradient conicalGradient(QPointF(200,100),0); // 创建一个对象 0表示angle
conicalGradient.setColorAt(0.2,Qt::cyan); // 设置渐变色 0-1 0到360*0.2=72度逐渐变为Qt::cyan
conicalGradient.setColorAt(0.4,Qt::black); // 设置渐变色 0-1 从72度到72+72度逐渐变为黑色
conicalGradient.setColorAt(0.7,Qt::red); // 设置渐变色 0-1 黑色渐变位红色
conicalGradient.setColorAt(0.7,Qt::yellow); // 设置渐变色 0-1
painter.setBrush(conicalGradient); // 利用锥形渐变作为画刷
painter.drawEllipse(QPointF(200,100),50,50);
}
抗锯齿
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// version 1
// QPen pen(QColor(255,0,0));
// painter.setPen(pen);
// version 2 创建匿名画笔
painter.setPen(QPen(Qt::red,15));
painter.drawEllipse(QPoint(200,200),100,100);
// 抗锯齿
painter.setRenderHints(QPainter::Antialiasing);
painter.translate(200,0); // 向右平移,相当于坐标系平移
painter.drawEllipse(QPoint(200,200),100,100);
}
坐标系变换
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
/* 坐标系旋转平移 */
painter.setPen(QPen(Qt::red,10));
// 直线
painter.drawLine(QPoint(10,10),QPoint(100,100));
painter.save(); // 保存当前坐标系(此时是初始状态)
painter.translate(200,0); // 坐标系平移200
painter.rotate(90); // 顺时针旋转90
/*
A --> A'
\ /
\ /
\/
B/B'
*/
painter.setPen(QPen(Qt::blue,10));
painter.drawLine(QPoint(10,10),QPoint(100,100));
/* 恢复坐标系 */
painter.restore();
painter.setPen(QPen(Qt::black,3));
painter.drawLine(QPoint(11,11),QPoint(200,200));
/* 坐标系旋转缩放 */
painter.setPen(QPen(Qt::red,3));
painter.setBrush(Qt::yellow); // 设置画刷用于填充
painter.drawRect(50,50,50,50); // 正方形
painter.save();
painter.scale(1.5,2);
painter.setBrush(Qt::green); // 设置画刷用于填充
painter.drawRect(50,50,50,50); // 正方形
}
容器路径
QPainterPath 表示一个容器,可以放置之前绘制的各种各样的图形
目标就是要重复绘制
void Widget::paintEvent(QPaintEvent*)
{
QPainter painter(this);
// 准备一个容器,设置容器内的内容
QPainterPath painterPath;
painterPath.moveTo(50,250); // 移动起始位置
painterPath.lineTo(50,200);
painterPath.lineTo(100,100);
painterPath.addEllipse(QPoint(100,100),30,30);
// 指定painter进行绘制
painter.setPen(Qt::red);
painter.drawPath(painterPath);
// 容器移动坐标系
painterPath.translate(200,0);
painter.setPen(Qt::blue);
painter.drawPath(painterPath);
}