Qt绘图 day9
基本绘图流程
-
Qt的绘制系统支持在屏幕和打印设备上使用相同的API进行绘制,主要基于QPainter、QPaintDevice和QPaintEngine类。
- QPainter:用于执行绘图操作
- QPaintDevice:用于二维空间的抽象
- QPainEngine:提供绘图器在不同类型的设备上绘图的接口
-
QPainter中提供了一些便捷函数来绘制常用的图形,还可以设置线条,边框的画笔以及进行填充个的画刷,所有对空间的绘图操作都要放进函数paintEvent()中,否则绘图无法显示
-
绘图流程
- 1.创建画家
- 2.设置绘图设备
- 3.进行绘制
- 4.让画家离开绘图设备
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//1.创建一个画家
QPainter painter;
//2.设置绘图设备
painter.begin(this);
//3.画一条线
painter.drawLine(0, 0, this->width(), this->height());
//4.让画家离开绘图设备
painter.end();
}
- QPainter提供的一些其他常用图形绘图函数
函数 | 功能 | 函数 | 功能 |
---|---|---|---|
drawChord | 绘制弦 | drawPolygon | 绘制多边形 |
drawArc | 绘制圆弧 | drawPoint | 绘制点 |
drawConvexPolygon | 绘制凸多边形 | drawPolyline | 绘制折线 |
drawElipse | 绘制椭圆 | drawRect | 绘制矩形 |
drawLine | 绘制线条 | drawRoundedRect | 绘制圆角矩形 |
drawPie | 绘制扇形 | fillRect | 绘制填充矩形 |
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
qDebug() << __FUNCTION__;
//1.创建一个画家
QPainter painter;
//设置绘图设备
painter.begin(this);
//画一条线
//painter.drawLine(0, 0, this->width(), this->height());
QList<QPointF> list{
{width() / 2.0,height() / 4.0},
{width() * 3 / 4.0,height() * 3 / 4.0},
{width() / 4.0,height() * 3 / 4.0},
//{width() / 2.0,height() / 4.0}
};
//绘制折现,一般把多个点一对一对的连接起来,不是每两个点相连
//painter.drawLines(list);
//绘制点与点之间连线,这里想连接成一个三角形就必须要第四条线
//painter.drawPolyline(list.data(),list.size());
//绘制多边形,这里就不需要第四条线,也可以连接成一个三角形
painter.drawPolygon(list.data(),list.size() );
//让画家离开绘图设备
painter.end();
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
使用画笔
- 给painter设置一个画笔QPen可以实现绘制线条不同的yanse
- Pen有样式(style),宽度(width),颜色(brush),笔帽样式(capStyle)与连接方式(joinStyle)
- style使用Qt::PenStyle定义线条类型,默认是Qt::PenStyle::SolidLine
- brush用与填充画笔生成的笔触,使用QBrush类来指定画笔颜色
- capStyle帽样式绝对使用QPainter的绘制线结束帽
- joinStyle连接样式描述了如何绘制两条线之间的连接
- 当更改画笔属性时,画家的比必须重置
void setPen(const QPen& pen)
void setPen(const QColor &color)
void setPen(Qt::PenStyle style)
线条样式
- style使用Qt::PenStyle定义线条类型,默认是Qt::PenStyle::SolidLine。
- QPen:
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
去锯齿
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
penStyle();
}
void penStyle()
{
//开启画家,使用构造方式开起画家不需要结束,会自动结束
QPainter painter(this);
//设置渲染提示,Antialiasing(高质量渲染)反锯齿
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
for (int i = 0; i < 6; i++)
{
painter.setPen(QPen(Qt::red, 5, Qt::PenStyle(i)));
painter.drawLine(i * 50, 0, i * 50 + 100, 200);
}
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
笔帽样式
-
有四种笔帽样式,Qt文档中只给了三种示例
void capStyle()
{
QPainter painter(this);
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::FlatCap));
painter.drawLine(0, 0, 100, 200);
painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::MPenCapStyle));
painter.drawLine(100, 0, 200, 200);
painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::RoundCap));
painter.drawLine(200, 0, 300, 200);
painter.setPen(QPen(QBrush(Qt::red), 5, Qt::PenStyle::DotLine, Qt::PenCapStyle::SquareCap));
painter.drawLine(300, 0, 400, 200);
}
- 运行结果
连接样式
- 实际有五种连接样式
- Qt文档中只给了四种
void joinStyle()
{
QPainter painter(this);
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
int s[] = { Qt::MiterJoin,Qt::BevelJoin,Qt::RoundJoin,Qt::SvgMiterJoin,Qt::MPenJoinStyle };
for (int i = 0; i < 5; i++)
{
painter.setPen(QPen(QBrush(Qt::red), 5, Qt::SolidLine, Qt::PenCapStyle::SquareCap, Qt::PenJoinStyle(s[i])));
//设置三角形的三个点
QPoint point[] = { {20 + i * 100,30},{50 + i * 100,60},{100 + i * 100,10} };
painter.drawPolygon(point, 3);
}
}
- 运行结果
设置画刷与线性渐变
- QBrush提供了画刷来对比图形进行填充,一个画刷使用它的颜色和风格来定义,Brush有样式(style)、颜色(color)、渐变(gradient)和纹理(texture)
- style使用Qt::BrushStyle定义填充模式,默认笔刷样式是Qt::NoBrush
- color定义填充图形颜色
- gradient()定义当前样式为Qt::LinearGradientPattern, Qt::RadialGradientPattern或Qt::ConicalGradientPattern时使用的渐变填充。 当创建QBrush时,通过给QGradient作为构造函数参数来创建渐变笔刷。 Qt提供三个不同的梯度:QLinearGradient, QConicalGradient,和QRadialGradient所有继承QGradient。
画刷填充样式与颜色填充
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
brushStyle();
brushStylePuls();
}
void brushStyle()
{
//定义画家与画刷颜色
QPainter painter(this);
painter.setBrush(Qt::red);
int w = 100;
int h = 100;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
painter.setBrush(Qt::BrushStyle(i * 5 + j));
painter.drawRect(i * w, j * h, w, h);
}
}
}
void brushStylePuls()
{
//定义画家与画刷颜色
QPainter painter(this);
painter.setBrush(Qt::red);
int w = 100;
int h = 100;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
//另一种带颜色的构造方式
painter.setBrush(QBrush(Qt::GlobalColor::blue, Qt::BrushStyle(i * 5 + j)));
painter.drawRect((i * w) + 350, j * h, w, h);
}
}
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
使用纹理填充
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
brushStylePulsMax();
}
void brushStylePulsMax()
{
//定义画家
QPainter painter(this);
//设置为无画笔
painter.setPen(Qt::NoPen);
painter.setBrush(QBrush(QPixmap(":/Resource/tubiao.ico")));
int w = 150;
int h = 150;
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 5; j++)
{
painter.drawRect(i * w, j * h, w, h);
}
}
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
渐变填充
- Qt目前支持三种类型的渐变填充:
- 线性渐变(QLinearGradient) 在开始点和结束点之间插入颜色。
- 径向渐变(QRadialGradient) 在围绕它的圆上的焦点和端点之间插入颜色。
- 锥形渐变(QConicalGradient) 在中心点周围插值颜色。
- 可以使用type()函数检索渐变的类型。 每一种类型都由QGradient的一个子类表示。
- QLinearGradient 显示从起点到终点的渐变。
线性渐变(QLinearGradient)
- lgra.setSpread(QGradient::PadSpread);设置渐变填充区之外的颜色
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
linearGradientPadSpread();
linearGradientRepeatSpread();
linearGradientReflectSpread();
}
void linearGradientPadSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(0,0,100,100);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::PadSpread);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(50, 50, 200, 200);
//绘制圆形
painter.drawEllipse(0, 0, 100, 100);
}
void linearGradientRepeatSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(260, 0, 360, 100);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::RepeatSpread);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(300, 50, 200, 200);
//绘制圆形
painter.drawEllipse(260, 0, 100, 100);
}
void linearGradientReflectSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(510, 0, 610, 100);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::ReflectSpread);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(550, 50, 200, 200);
//绘制圆形
painter.drawEllipse(510, 0, 100, 100);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
- 通过这种坐标设置填充就很麻烦,一旦绘图位置变了,就得更新填充,所以它的父类中有一个方法可以设置一下坐标模式
- 我们一般使用第二种模式、
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
linearGradientPadSpread();
linearGradientRepeatSpread();
linearGradientReflectSpread();
}
void linearGradientPadSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(0,0,1,1);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::PadSpread);
//设置梯度坐标模式
lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(50, 50, 200, 200);
//绘制圆形
painter.drawEllipse(0, 0, 100, 100);
}
void linearGradientRepeatSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(0, 0, 1, 1);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::RepeatSpread);
//设置梯度坐标模式
lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(300, 50, 200, 200);
//绘制圆形
painter.drawEllipse(260, 0, 100, 100);
}
void linearGradientReflectSpread()
{
//定义线性渐变
//Constructs a linear gradient with interpolation area between (x1, y1) and (x2, y2).
QLinearGradient lgra(0, 0, 1, 1);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
lgra.setColorAt(0, Qt::red);
lgra.setColorAt(0.48, Qt::blue);
lgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
lgra.setSpread(QGradient::ReflectSpread);
//设置梯度坐标模式
lgra.setCoordinateMode(QGradient::CoordinateMode::ObjectMode);
//把渐变交给画刷
painter.setBrush(lgra);
//绘制矩形
painter.drawRect(550, 50, 200, 200);
//绘制圆形
painter.drawEllipse(510, 0, 100, 100);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
+运行结果
- 因为使用了对象模式,即绘画的圆形和矩形都采用统一的渲染,默认渲染
径向渐变(QRadialGradient)
- QRadialGradient 类以圆心为中心显示渐变。(cx, cy) 是中点,半径(radius)是以中点为圆心的圆的半径,(fx, fy) 是渐变的起点。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
radialGradientPadSpread();
}
void radialGradientPadSpread()
{
//指定以圆心和半径,以圆心为中心渐变
QRadialGradient rgra(50, 50, 50);
//也可以在构造对象后通过函数,设置开始点和结束点
//rgra.setCenter(50, 50);
//下面两个设置半径的功能一样
//rgra.setRadius(50);
//rgra.setCenterRadius(50);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
rgra.setColorAt(0, Qt::red);
rgra.setColorAt(0.48, Qt::blue);
rgra.setColorAt(1, Qt::yellow);
//开启画家
QPainter painter(this);
//设置填充渐变区域之外的区域
rgra.setSpread(QGradient::ReflectSpread);
//把渐变交给画刷
painter.setBrush(rgra);
//绘制矩形
painter.drawRect(50, 50, 200, 200);
//绘制圆形
painter.drawEllipse(0, 0, 100, 100);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
锥形渐变(QConicalGradient)
- QConicalGradient圆锥渐变在一个中心点周围逆时针插入颜色, 在 (cx, cy) 坐标上以角度 (angle) 为中心显示渐变。
- 角度必须在0到360度之间指定。
void conicalGradient()
{
//指定以圆心和角度进行渐变
QConicalGradient cgra(50, 50, 0);
//也可以在构造对象后通过函数,设置圆心和角度
//cgra.setAngle(0);
//cgra.setCenter(50, 50);
//用给定的位置(比例:0~1)和颜色设置过度点,在哪里切换颜色
cgra.setColorAt(0, qRgb(82, 113, 196));
cgra.setColorAt(0.48, qRgb(177, 159, 255));
cgra.setColorAt(1, qRgb(236, 161, 254));
QPainter painter(this);
//把渐变色设置给画刷
painter.setBrush(cgra);
//绘制矩形,观察渐变区域之外的区域的填充
painter.drawRect(50, 50, 250, 250);
//绘制圆形(这里一般和开始指定的渐变坐标一样)
painter.drawEllipse(0, 0, 100, 100);
}
坐标变换
- QTransform 用于指定坐标系的 2D 转换 - 平移、缩放、扭曲(剪切)、旋转或投影坐标系。通常在渲染现图形时使用。
- 可以使用setMatrix()、scale()、rotate()、translate()和shear()函数来构建QTransform对象。或者,也可以通过应用基本的矩阵操作来构建它。矩阵也可以在构造时定义,并且可以使用reset()函数将其重置为单位矩阵(默认值)。
- QPainter具有平移、缩放、剪切和旋转坐标系统的功能,无需使用QTransform。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
transform(&painter);
}
void transform(QPainter* painter)
{
painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
平移
- translate(qreal dx, qreal dy):平移 - 对坐标系沿着 x 轴移动 dx、沿 y 轴移动 dy
void transform(QPainter* painter)
{
//平移
painter->translate(50, 50);
painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
}
缩放
- scale(qreal sx, qreal sy):缩放 - 通过水平的 sx 和垂直的 sy 缩放坐标系
void transform(QPainter* painter)
{
//平移
painter->translate(50, 50);
//缩放
painter->scale(0.5, 0.5);
painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
}
- 运行结果
旋转
- rotate(qreal angle, Qt::Axis axis = Qt::ZAxis):旋转 - 对指定的轴用给定的角度逆时针旋转坐标系统
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
auto timer = new QTimer(this);
//每60帧调用一次绘图
timer->callOnTimeout([=]()
{
//更新绘图不能手动调用paintEvent
//paintEvent(nullptr);
//必须调用update函数更新绘图
this->update();
}
);
timer->start(1000 / 60);
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
transform(&painter);
}
//旋转值
qreal angle = 0;
void transform(QPainter* painter)
{
//平移
painter->translate(50, 50);
//缩放
painter->scale(0.5, 0.5);
//旋转.默认是绕z轴转
//painter->rotate(angle++);
//绕x轴转
QTransform tfm;
//tfm.rotate(angle++, Qt::Axis::XAxis);
//painter->setTransform(tfm);
//绕y轴转
//tfm.rotate(angle++, Qt::Axis::YAxis);
//painter->setTransform(tfm);
//绕z轴转
tfm.rotate(angle++, Qt::Axis::ZAxis);
painter->setTransform(tfm);
painter->drawPixmap(0,0,QPixmap(":/Resource/tubiao.ico"));
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
auto timer = new QTimer(this);
//每60帧调用一次绘图
timer->callOnTimeout([=]()
{
//更新绘图不能手动调用paintEvent
//paintEvent(nullptr);
//必须调用update函数更新绘图
this->update();
}
);
timer->start(1000 / 60);
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
transform(&painter);
}
//旋转值
qreal angle = 0;
void transform(QPainter* painter)
{
QPixmap map(":/Resource/tubiao.ico");
//The QTransform class specifies 2D transformations of a coordinate system
QTransform tfm;
//移动
tfm.translate(width() / 2, height() / 2);
//缩放
tfm.scale(0.5, 0.5);
//绕z轴转
tfm.rotate(angle++, Qt::Axis::ZAxis);
painter->setTransform(tfm);
painter->drawPixmap(0 - map.width() / 2, 0 - map.height() / 2, map);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
错切
- 图像错切变换也称为图像剪切、错位或错移变换。
- shear(qreal sh, qreal sv):错切 - 通过水平的 sh 和垂直的 sv 扭曲坐标系,前面的参数实现横向变形,后面的参数实现纵向变形。当它们的值为 0 时,表示不扭曲。
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
auto timer = new QTimer(this);
//每60帧调用一次绘图
timer->callOnTimeout([=]()
{
//更新绘图不能手动调用paintEvent
//paintEvent(nullptr);
//必须调用update函数更新绘图
this->update();
}
);
timer->start(1000 / 60);
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
transform(&painter);
}
//旋转值
qreal angle = 0;
void transform(QPainter* painter)
{
QPixmap map(":/Resource/tubiao.ico");
//The QTransform class specifies 2D transformations of a coordinate system
QTransform tfm;
//移动
tfm.translate(width() / 2, height() / 2);
//缩放
tfm.scale(0.5, 0.5);
//错切
tfm.shear(0.5, 0);
//绕z轴转
tfm.rotate(angle++, Qt::Axis::ZAxis);
painter->setTransform(tfm);
painter->drawPixmap(0 - map.width() / 2, 0 - map.height() / 2, map);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
QPixmap、QImage、QBitmap、QPicture
- Qt提供四种处理图像数据的类:QImage、QPixmap、QBitmap、QPicture
- QImage是为I/O和直接像素访问和操作而设计和优化的,而QPixmap是为在屏幕上显示图像而设计和优化的。 QBitmap只是一个继承了QPixmap的方便类,确保深度为1。 如果QPixmap对象是位图,则isQBitmap()函数返回true,否则返回false。 最后,QPicture类是一个记录和回放QPainter命令的绘图设备。
QPixmap
void pixmap(QPainter* painter)
{
//构造一个图像对象
QPixmap pix(":/Resource/tubiao.ico");
//绘画这个图像到0,0坐标
//painter->drawPixmap(0, 0, pix);
painter->drawPixmap(QRect(0, 0, 50, 50), pix);
//剪切图像
painter->drawPixmap(0, 50, pix, 0, 0, 200, 200);
painter->drawPixmap(QRect(0, 250, 100, 100), pix, QRect(100, 100, 200, 200));
}
- 运行结果
QImage
- QGradient:里面会有很多预设颜色
- 一般构造QImage的时候,QImage::Format格式,这个比较常用
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
//声明QImage对象
QImage m_image;
Widget(QWidget* parent = nullptr) :QWidget(parent)
,m_image(200,200,QImage::Format::Format_RGBA8888)
{
//在QImage上绘图
{
QPainter painter(&m_image);
//在这个矩形上绘制,渐变模式为WinterNeva
painter.fillRect(m_image.rect(),QGradient::WinterNeva);
}
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
image(&painter);
}
void image(QPainter* painter)
{
painter->drawImage(0, 0, m_image);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
QBitmap
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QTimer>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
bitmap(&painter);
}
void bitmap(QPainter* painter)
{
QPixmap pix(":/Resource/tubiao.ico");
painter->drawPixmap(0, 0, QBitmap::fromPixmap(pix));
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果
QPicture
#include <QApplication>
#include <QWidget>
#include <QEvent>
#include <QPainter>
#include <QPoint>
#include <QPicture>
class Widget :public QWidget
{
public:
Widget(QWidget* parent = nullptr) :QWidget(parent)
{
}
protected:
//所有在widget上的绘制,必须放在paintEvent函数里面,paintEvent在需要绘图时会自动调用
void paintEvent(QPaintEvent* ev) override
{
//一般调用多个绘图,可以先在这里构造个对象传入函数,就没有必要构造多个对象
QPainter painter(this);
picture(&painter);
}
void picture(QPainter* painter)
{
QPicture pic;
{
//先让pt与pic取消关联后,才能保存,用块语句包裹即可
QPainter pt(&pic);
pt.drawLine(0, 0, width(), height());
pt.fillRect(100, 200, 150, 35, QGradient::Preset::SkyGlider);
}
//保存到本地,这个里面保存的是指令只有qt看得懂
pic.save("text.pic");
//显示图像
QPicture picc;
picc.load("text.pic");
painter->drawPicture(0, 0, picc);
//picc.play(painter);
}
private:
};
int main(int argc, char* argv[])
{
QApplication a(argc, argv);
Widget w;
w.setWindowIcon(QIcon(":/Resource/tubiao.ico"));
w.show();
return a.exec();
}
#include "main.moc"
- 运行结果,本地的out目录里面会有一个text.pic文件