坐标变换
平移坐标轴
painter.translate(50,50);
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(150,100));
缩放坐标轴
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(100,100));
painter.scale(0.5,0.5);
painter.drawPixmap(200,200, QPixmap(":/bk1.jpg").scaled(100,100));
旋转坐标轴
painter.translate(width()/2 - 100,height()/2 - 100);
painter.rotate(30); // 角度(默认以坐标原点旋转)(正数顺时针,负数逆时针)
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(200,200));
定时器加坐标轴旋转实现动画旋转
QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
static int angle = 0;
painter.translate(width()/2 - 100,height()/2 - 100);
painter.rotate(angle++);
painter.drawPixmap(0,0, QPixmap(":/bk1.jpg").scaled(200,200));
transform旋转(可设置旋转轴)
绕X轴旋转
QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::XAxis); // 绕X轴旋转
painter.setTransform(transform);
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));
绕Y轴旋转
QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::YAxis); // 绕Y轴旋转
painter.setTransform(transform);
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));
绕Z轴旋转
QTimer* timer = new QTimer(this);
timer->callOnTimeout(this, QOverload<>::of(&QWidget::update));
timer->start(10);
//
static int angle = 0;
QTransform transform;
transform.rotate(angle++, Qt::ZAxis); // 绕Z轴旋转
painter.setTransform(transform);
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));
错切
Y轴错切
// y轴错切
painter.translate(width()/2 - 100, height()/2 -100);
painter.shear(0, 0.5); // [-1, 1]
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));
X轴错切
// x轴错切
painter.translate(width()/2 - 100, height()/2 -100);
painter.shear(0.5, 0); // [-1, 1]
painter.drawPixmap(0, 0 , QPixmap(":/bk1.jpg").scaled(200,200));
画家的保存与坐标复原
painter.save(); // 画家状态保存
// 坐标变换
// 图形绘制
painter.restore(); // 画家状态复原
基本图形绘制
绘制点
painter.setPen(Qt::red);
painter.drawPoint(50,50); // 绘制单个点
// 绘制多个点
QPoint points[] = {
{0,0},{1,1},{2,2},{3,3}};
painter->drawPoints(points, 4);
// 绘制多个点
QPolygon polygon;
for(int i = 0; i < 100; i++)
{
polygon.append({i,i});
}
painter.drawPoints(polygon);
绘制线
// 绘制一条线
painter.drawLine(0,0,100,100);
// 绘制多条线
QList<QLine> lines = {
{0,0,100,100}, {100,100, 0,200}};
painter.drawLines(lines);
绘制矩形
普通矩形绘制
painter.drawRect(50,50,100,100);
圆角矩形绘制
// 最后一个参数为默认值,此时第三第四个参数为具体的值
painter.drawRoundedRect(QRect(200,200,100,100), 50, 50,Qt::SizeMode::AbsoluteSize);
// 此时第三第四个参数为百分比 [0,100]
painter.drawRoundedRect(QRect(200,200,100,100), 50, 50,Qt::SizeMode::RelativeSize);
填充矩形绘制
painter.fillRect(50,50,100,100,QColor(255,0,255));
绘制圆形
painter.drawEllipse(0,0,200,200); // 矩形区域绘制
painter.drawEllipse(QPoint(100,100),50,50); // 中心点,两轴
绘制弧、扇形、弦
绘制弧
painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawArc(QRect(100,100,200,200), 0, 16 * 90);
绘制扇形
painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawPie(QRect(100,100,200,200), 0, 16 * 90);
绘制弦
painter.drawRect(100,100,200,200);
painter.setPen(Qt::red);
painter.drawChord(QRect(100,100,200,200), 0, 16 * 90);
绘制折线
QPolygon poly;
poly << QPoint(0, 0) << QPoint(100,100) << QPoint(200, 100);
painter.drawPolyline(poly);
QPoint pos[3] = { QPoint(0, 0) , QPoint(100,100) , QPoint(200, 100)};
painter.drawPolyline(pos, 3);
绘制多边形
painter.setBrush(Qt::green);
QPolygon poly = {
{0,0},{100,0},{100,100},{0,100},{200,0}};
painter.drawPolygon(poly);
绘制路径
基本路径绘制
painter.setBrush(Qt::green);
QPainterPath path;
path.lineTo(200,200);
path.lineTo(0,200);
path.moveTo(400,400);
path.lineTo(width(),height());
painter.drawPath(path);
填充规则
painter.setBrush(Qt::green);
QPainterPath path;
path.addRect(QRect(0,0,200,200));
path.addRect(QRect(100,100,200,200));
path.setFillRule(Qt::FillRule::WindingFill); // 缠绕填充
//path.setFillRule(Qt::FillRule::OddEvenFill); // 奇偶填充
painter.drawPath(path);
绘制贝塞尔曲线
二次贝塞尔曲线绘制
// 二次贝塞尔曲线
QPainterPath path;
path.moveTo(200,200);
path.quadTo(QPoint(300,300), QPoint(400,200));
painter.drawPath(path);
三次贝塞尔曲线绘制
// 三次贝塞尔曲线
QPainterPath path;
path.moveTo(0,0);
path.cubicTo(QPoint(10,100), QPoint(300,500), QPoint(200,200));
painter.drawPath(path);
绘制文字
静态文本绘制
// 绘制坐标即为左上角坐标
painter.drawStaticText(QPoint(0,0), QStaticText("Hello World"));
普通文本绘制
注意: 绘制文字是以左下角为原点绘制的
painter.setPen(Qt::red);
painter.setFont(QFont("微软雅黑",28,QFont::Bold,true));
painter.drawText(0,50, QString("Hello World"));
// 将绘制字体固定在矩形区域内 (会自动换行)
painter.drawText(QRect(0,0,100,200), "Hello World Hello World!");
字体相关函数
// 设置字体
painter->setFont();
// 获取字体
painter->font();
// 获取字体信息
painter->fontInfo();
// 获取字体数据
painter->fontMetrics();
图片绘制
QPixmap
针对输出显示优化的图像绘制
指定位置裁剪
painter.drawPixmap(100, 100, QPixmap("mm.jpg").scaled(100,100));
painter.drawPixmap(QRect(0,0,100,100), // 绘制位置
QPixmap("mm.jpg").scaled(100,100), // 图像
QRect(50,50,50,50)); // 裁剪区域
drawPixmap(const QPoint &point, const QPixmap &pixmap, const QRect &source)
透明绘制
分别准备一张原码图和一张掩码图
//掩码图和原图大小必须一致
//掩码图白色区域为透明,黑色区域为绘制
painter.setRenderHint(QPainter::RenderHint::Antialiasing);
QBitmap mask("mask.jpg");
QPixmap pix = QPixmap("snowball.jpg").scaled(mask.size());
pix.setMask(mask);
painter.drawPixmap(0, 0,pix);
瓦片图绘制
// 函数原型
drawPixmapFragments(const QPainter::PixmapFragment *fragments,
int fragmentCount,
const QPixmap &pixmap,
QPainter::PixmapFragmentHints hints = PixmapFragmentHints())
QPainter::PixmapFragment pixFrag = QPainter::PixmapFragment::create(QPointF(0,0), QRectF(0,0,100,100));
painter.drawPixmapFragments(&pixFrag, 2, QPixmap("mm.jpg").scaled(100,100));
图像的保存
m_pixmap = QPixmap(640,480);
QPainter painter(&m_pixmap);
painter.fillRect(m_pixmap.rect(),Qt::blue);
// 保存图片
m_pixmap.save("hello.png");
QImage
专门进行图像处理的
QImage m_img = QImage(640,480,QImage::Format_RGBA8888);
m_img.fill(Qt::transparent);
QPainter painter(&m_img);
painter.fillRect(QRect(0,0,100,100), Qt::blue);
m_img.save("img.png");
QPicture
Qt独有的图像格式
QPainter painter;
painter.begin(&pic);
painter.drawEillipse(0,0,200,200);
painter.end();
pic.save("pic.pic");
// 绘制不能直接使用QPicture的构造函数加载文件
QPicture pict;
pict.load("pic.pic");
painter->drawPicture(0,0,pict);
QBitmap
位图(黑白图)
QBitmap bitmap("mm.jpg");
painter.drawImage(QRect(0, 0, 100, 100), bitmap.toImage());
碰撞检测
// 碰撞检测
#include <QApplication>
#include <QWidget>
#include <QPainter>
#include <QStaticText>
#include <QPainterPath>
#include <QKeyEvent>
// 碰撞检测
class Sprite
{
public:
Sprite() = default;
Sprite(int x,int y,int w,int h, const QPixmap& pix)
:m_pos(x,y),m_size(w,h),m_pixmap(pix)
{
}
void draw(QPainter* painter)
{
painter->drawPixmap(QRect(m_pos,m_size), m_pixmap);
}
void setPos(int x,int y)
{
m_pos.rx() = x;
m_pos.ry() = y;
}
void moveBy(int dx,int dy)
{
m_pos.rx() += dx;
m_pos.ry() += dy;
}
void updateCollider()
{
collider.clear();
collider.addRect(QRect(m_pos, m_size));
}
void printPos()
{
qInfo() << m_pos;
}
private:
QPoint m_pos;
QSize m_size;
QPixmap m_pixmap;
public:
QPainterPath collider; // 碰撞器
};
class Widget : public QWidget
{
Q_OBJECT
public:
Widget(QWidget* parent = nullptr)
:QWidget(parent)
{
resize(640,480);
sp1 = new Sprite(0,0,50,50,QPixmap("mm.jpg"));
sp2 = new Sprite(100,0,50,50, QPixmap("snowball.jpg"));
}
~Widget()
{
}
protected:
void paintEvent(QPaintEvent* ev) override
{
QPainter painter(this);
sp1->draw(&painter);
sp2->draw(&painter);
}
void keyPressEvent(QKeyEvent *ev) override
{
switch(ev->key())
{
case Qt::Key_Up:
sp2->moveBy(0, -3);
break;
case Qt::Key_Down:
sp2->moveBy(0, 3);
break;
case Qt::Key_Left:
sp2->moveBy(-3, 0);
break;
case Qt::Key_Right:
sp2->moveBy(3, 0);
break;
}
if(sp1->collider.intersects(sp2->collider))
{
sp2->setPos(width() - 50, 0);
}
update();
// 判断碰撞
sp2->updateCollider();
sp1->updateCollider();
}
private:
Sprite* sp1 = nullptr;
Sprite* sp2 = nullptr;
};
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Widget w;
w.show();
return a.exec();
}
#include "main.moc"