本文已参加【新人创作礼】活动,一起开启掘金创作之路。
📒博客首页:何名取 的个人主页 - 文章 - 掘金 (juejin.cn)
🎉欢迎关注🔎点赞👍收藏⭐️留言📝
❤️期待一起交流!
🙏作者水平很有限,如果发现错误,求告知,多谢!
🌺有问题可私信交流!!!
绘制吉祥物
前言
之前冬奥期间吉祥物可谓是火上了天,当时也想买一个挂件或者玩偶,可惜当时产能有限没抢到。最近这两天大大小小的路口都看见有在摆摊卖吉祥物挂件的,东西多了反倒没那个购买欲望了。想着用Qt的QPainter来画一个吧,免费也不占地方。网上有大佬已经将吉祥物的绘制坐标发出来了,咱就直接嫖他的,代码自己写。
用QPainter绘制好吉祥物之后,再将定义吉祥物的C++类导入到QML中,让吉祥物在QML视图中与小伙伴们见面,完成从C++到QML的旅程。
QPainter简介
QPainter提供了大量高度优化的功能来满足大多数绘图GUI程序需要。它可以画任何东西,从简单的线条到复杂的形状,比如派和和弦。它还可以绘制对齐的文本和像素地图。通常,它在一个“自然”坐标系中绘制,但它也可以进行视图和领域转换。
熟悉Qt的小伙伴们应该听说过大名鼎鼎的QPainter,在Qt中进行重绘和创建自定义控件基本都会用到它,就像它的名字“画笔”,用好QPainter,人人都是神笔马良。
本节用到的QPainter函数
QPainter类中有非常多的函数,本节使用的函数只是其中的一部分,因此只介绍本节使用到的函数。
函数名 | 功能 |
---|---|
scale | 缩放扩张,可以指定沿x轴、y轴放缩的比例 |
setPen | 设置画笔,一般设置颜色和粗细 |
setRenderHint | 设置抗锯齿 |
drawPath | 绘制给定的绘图器路径 |
save | 保存当前绘图器状态(将状态压入堆栈)。save()后面必须有相应的restore()函数,其作用是展开堆栈。 |
setBrush | 设置笔刷,一般用于填充 |
restore | 恢复当前画家状态(从堆栈中弹出一个保存的状态) |
drawEllipse | 绘制由给定矩形定义的椭圆 |
另外因为吉祥物不是非常规则的简单图形,在绘制吉祥物时要用到贝塞尔曲线。可以使用QPainterPath类中的相应函数来进行绘制。
函数名 | 功能 |
---|---|
moveTo | 移动画笔到此处 |
cubicTo | 设置一段三次贝塞尔曲线 |
quadTo | 设置一段二次贝塞尔曲线 |
下面是一段绘制吉祥物的代码。由于整段代码过长影响阅读,因此只截取其中绘制外形的代码,完整代码见文章结尾处链接。
QPen pen(m_color,2);
painter->scale(0.37,0.37);
painter->setPen(pen);
painter->setRenderHint(QPainter::Antialiasing);
// 能量外壳
QPainterPath path0;
path0.moveTo(497,462);
path0.cubicTo(452,380,497,184,666,297);
path0.cubicTo(792,255,921,261,1017,278);
path0.cubicTo(1127,155,1227,305,1183,404);
path0.cubicTo(1208,443,1238,488,1254,544);
path0.cubicTo(1251,421,1503,398,1472,577);
path0.cubicTo(1407,758,1336,789,1279,876);
path0.cubicTo(1270,924,1255,1044,1147,1222);
path0.cubicTo(1098,1372,1211,1454,1031,1457);
path0.cubicTo(877,1469,892,1434,901,1376);
path0.cubicTo(924,1313,783,1324,802,1378);
path0.cubicTo(822,1432,819,1467,691,1469);
path0.cubicTo(571,1473,569,1448,571,1332);
path0.cubicTo(572,1218,530,1226,464,1038);
path0.cubicTo(386,1244,233,1115,272,1017);
path0.cubicTo(306,916,365,845,407,777);
path0.cubicTo(433,669,449,545,497,462);
painter->drawPath(path0);
painter->save();
将C++类集成到QML中
文件结构
完成了吉祥物的绘制以后,需要将C++的类集成到QML中。以下是文件结构:
bingdundun.cpp即是我们绘制吉祥物的类,此时的.cpp文件与main.qml毫无关系,运行代码也没有吉祥物出现。这时就需要将C++类集成到QML中。
集成步骤
更改头文件
#ifndef BINGDUNDUN_H
#define BINGDUNDUN_H
#include <QQuickPaintedItem>
#include <QQuickItem>
class BingDunDun : public QQuickPaintedItem
{
Q_OBJECT
Q_PROPERTY(QString name READ name WRITE setName)
Q_PROPERTY(QColor color READ color WRITE setColor)
QML_ELEMENT
public:
BingDunDun(QQuickItem *parent = 0);
QString name() const;
void setName(const QString &name);
QColor color() const;
void setColor(const QColor &color);
void paint(QPainter *painter);
private:
QString m_name;
QColor m_color;
};
#endif // BINGDUNDUN_H
Q_PROPERTY宏声明了一个可以从QML访问的属性。QML_ELEMENT宏使后端类在QML中可用。这里的主要目的就是把属性暴露给QML,让QML可以得到C++类中定义的属性。
注册QML模块
在main.cpp中注册吉祥物的QML模块。
#include <QGuiApplication>
#include <QQmlApplicationEngine>
#include "bingdundun.h"
int main(int argc, char *argv[])
{
#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
#endif
QGuiApplication app(argc, argv);
qmlRegisterType<BingDunDun>("Bingdundun",1,0,"BingDunDun");
QQmlApplicationEngine engine;
const QUrl url(QStringLiteral("qrc:/main.qml"));
QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
&app, [url](QObject *obj, const QUrl &objUrl) {
if (!obj && url == objUrl)
QCoreApplication::exit(-1);
}, Qt::QueuedConnection);
engine.load(url);
return app.exec();
}
这里与原来的main.cpp不同之处在于使用qmlRegisterType("Bingdundun",1,0,"BingDunDun"); 对吉祥物的C++类进行了注册,完成以后即可以模块的形式导入QML中使用。需要注意的是,注册函数一般用在 QQmlApplicationEngine engine; 之前。
将吉祥物模块导入.qml中
import QtQuick 2.15
import QtQuick.Window 2.15
import Bingdundun 1.0
Window {
width: 640
height: 640
visible: true
title: qsTr("Hello World")
BingDunDun {
id: bingdundun
anchors.centerIn: parent
anchors.fill: parent
name: "A bingdundun"
color: "blue"
}
Text {
anchors { bottom: parent.bottom; horizontalCenter: parent.horizontalCenter; bottomMargin: 20 }
font.bold: true
font.pixelSize: 20
font.family: "黑体"
text: bingdundun.name
color: bingdundun.color
}
}
此时就可将吉祥物模块导入到.qml中使用了,导入方法非常简单,插入import Bingdundun 1.0即可。此时吉祥物已经完成了它的奇幻之旅,从C++类中跑到了QML视图中来。
效果展示
更改main.qml中吉祥物的name属性和color属性,可以有不同的颜色效果,欢迎小伙伴们尝试。
完整代码链接gitee.com/heyufeng471…