Qt QML 使用QPainterPath绘制弧形曲线和弧形文本

Qt并没有相关api直接绘制弧形文字,但提供了曲线绘制相关类,所以只能另辟蹊径,使用QPainterPath先生成曲线,然后通过曲线上的点来定位每个文字并draw出来。

QML具体做法为从QQuickPaintedItem继承,在派生类中实现paint函数

代码如下:

cpp 复制代码
void ViewItem::paint(QPainter *painter)
{
    painter->setRenderHint(QPainter::Antialiasing);
    
    QRectF rect(200, 200, 400, 300);
    painter->drawRect(rect);
    
    auto arcRect = rect;
    arcRect.setHeight(rect.height() * 2); //绘制椭圆上半圆,所以椭圆矩形高度*2
    
    QPainterPath path;
    path.arcMoveTo(arcRect, 170);  //起始度数
    path.arcTo(arcRect, 170, -160); //起始度数,曲线弧度
    
    painter->drawPath(path);
    
    QFont font("", 20);
    painter->setFont(font);
    
    QFontMetrics fm(font);    
    auto textH = fm.height();
    
    QString text = "测试QML弧形文字绘制";
    for(auto i=0; i< text.length(); i++)
    {
        const auto& word = text.at(i);
                
        painter->save();
        
        auto per = i / (float)(text.length() - 1);
        
        auto pt = path.pointAtPercent(per);
        painter->translate(pt.x(), pt.y());
        
        auto ang = path.angleAtPercent(per);
        painter->rotate(-ang);
        
        auto textW = fm.horizontalAdvance(word);        
        painter->drawText(-textW/2, 0, textW, textH, Qt::AlignCenter, word);
        
        painter->restore();
    }   
}

曲线与文本效果如下:

关于度数说明,如下图

上半圆从右往左,逆时针0°到180°,所以为了使线条从从往右绘制,所以起始度数设置为170°(具体看个人需求),曲线弧度负数为反向,左边-10,右边-10,故为-160°(具体看个人需求)

复制代码
QPainterPath path;
path.arcMoveTo(arcRect, 170);  //起始度数
path.arcTo(arcRect, 170, -160); //起始度数,曲线弧度

使用QPainterPath的两个函数pointAtPercent和angleAtPercent,能获取到每个文本对于的位置和旋转角度。

drawText注意文字偏移即可。

凹形曲线,使用椭圆下半圆使用相同方法绘制即可。

相关推荐
一条咸鱼_SaltyFish1 小时前
远程鉴权中心设计:HTTP 与 gRPC 的技术决策与实践
开发语言·网络·网络协议·程序人生·http·开源软件·个人开发
我即将远走丶或许也能高飞1 小时前
vuex 和 pinia 的学习使用
开发语言·前端·javascript
沐知全栈开发1 小时前
SQL LEN() 函数详解
开发语言
钟离墨笺2 小时前
Go语言--2go基础-->基本数据类型
开发语言·前端·后端·golang
小郭团队2 小时前
1_7_五段式SVPWM (传统算法反正切+DPWM3)算法理论与 MATLAB 实现详解
开发语言·嵌入式硬件·算法·matlab·dsp开发
C+-C资深大佬2 小时前
C++风格的命名转换
开发语言·c++
No0d1es2 小时前
2025年粤港澳青少年信息学创新大赛 C++小学组复赛真题
开发语言·c++
点云SLAM2 小时前
C++内存泄漏检测之手动记录法(Manual Memory Tracking)
开发语言·c++·策略模式·内存泄漏检测·c++实战·new / delete
码上成长3 小时前
JavaScript 数组合并性能优化:扩展运算符 vs concat vs 循环 push
开发语言·javascript·ecmascript
打工的小王3 小时前
java并发编程(三)CAS
java·开发语言