(15)Qt绘图(two)

简介: Qt框架中QPainter类的多种绘图功能,包括坐标变换、基本图形绘制、文本和图片绘制、图像保存以及碰撞检测等。

坐标变换

平移坐标轴

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"

相关文章
|
11月前
|
编解码 图形学
29 QT - 绘图设备
29 QT - 绘图设备
36 0
|
存储 算法 数据可视化
Qt开发技术:Qt绘图系统(二)QPainter详解
Qt开发技术:Qt绘图系统(二)QPainter详解
Qt开发技术:Qt绘图系统(二)QPainter详解
|
存储 编解码 缓存
Qt开发技术:Qt绘图系统(一)绘图系统介绍
Qt开发技术:Qt绘图系统(一)绘图系统介绍
Qt开发技术:Qt绘图系统(一)绘图系统介绍
|
2月前
|
容器
【qt】GraphicsView绘图架构
【qt】GraphicsView绘图架构
56 0
|
2月前
【qt】绘图
【qt】绘图
28 0
|
3天前
(14)Qt绘图(one)
本文介绍了在Qt中使用QPainter进行绘图的基础操作,包括如何指定绘图设备、使用QPen和QBrush设置线条和填充样式、绘制不同样式的线条和形状,以及如何实现纹理填充和渐变填充等效果。
19 6
(14)Qt绘图(one)
|
3天前
|
存储 Windows
(13) Qt事件系统(two)
文章详细介绍了Qt事件系统,包括事件分发、自定义事件、事件传播机制、事件过滤以及事件与信号的区别。
19 3
(13) Qt事件系统(two)
|
2月前
|
API
Qt绘图之Paint系统
Qt绘图之Paint系统
48 2
|
2月前
Qt绘图之QWidget
Qt绘图之QWidget
55 1
|
4月前
Qt绘图(线条、椭圆、矩形、图片滚动)
Qt绘图(线条、椭圆、矩形、图片滚动)
209 3