赞
踩
1966年,Seymour Papert 和 Wally Feurzig 发明了一种专门给儿童学习编程的语言——LOGO 语言,它的特色就是通过编程指挥一个小海龟(turtle)在屏幕上绘图。海龟绘图(Turtle Graphics)后来被移植到各种高级语言中,Python内置了 turtle 库,基本上完整复制了原始 Turtle Graphics 的所有功能。
海龟绘图的特点就是以动画的形式绘制出图案,这比直接展示最终图案更有趣。
要在 Qt 中实现这种动画效果,我的思路就是通过定时器刷新当前进度,然后根据进度来决定绘制哪一部分。趁着假期无聊就写了个简易版本的,可以画直线和圆弧,以及填充路径,后面有空再完善下。
代码链接:https://github.com/gongjianbo/QtTurtle
效果展示:
调用代码:
- drawPainter.begin(QPointF(300,200));
- drawPainter.beginFill(QColor(0,100,0));
- drawPainter.setPenWidth(2);
- drawPainter.setPenColor(QColor(0,150,0));
- drawPainter.arc(QPointF(200,200),100,0,180);
- drawPainter.arc(QPointF(400,100),318,-161,53);
- drawPainter.arc(QPointF(200,100),318,-72,53);
- drawPainter.arc(QPointF(400,200),100,0,180);
- drawPainter.endFill();
- drawPainter.end();
核心部分就是每一步操作就 new 一个对象,绘制时遍历这些对象,遍历过程中超出当前进度就 break,等定时器 timeout 时进度会增加并再次遍历绘制。
部分代码:
- #include "MyPainter.h"
-
- #include <QtMath>
- #include <QDebug>
-
- MyPainter::MyPainter(QObject *parent) : QObject(parent)
- {
- timer=new QTimer(this);
- connect(timer,&QTimer::timeout,this,[=]{
- drawLength+=10;
- update();
-
- //时长超过表示线条绘制完了
- if(drawEnd)
- timer->stop();
- });
- }
-
- MyPainter::~MyPainter()
- {
- qDeleteAll(dataList);
- dataList.clear();
- }
-
- void MyPainter::draw(QPaintDevice *device)
- {
- if(drawLength<=0)
- return;
- QPainter painter(device);
-
- //目前没有设置路径填充规则 TODO
- qint64 progress_temp=0;
- int i=0;
- for(i=0;i<dataList.count()&&progress_temp<drawLength;i++)
- {
- double len=drawLength-progress_temp;
- AbstractElement* item=dataList[i];
- //判断begin和end fill,执行到endfill才开始填充begin中的路径
- switch (item->type()) {
- case 3:
- {
- const int ele_index=static_cast<BeginFillElement*>(item)->index();
- if(drawEndIndex>=ele_index){
- item->draw(&painter,0);
- }
- }
- break;
- case 4:
- drawEndIndex=static_cast<EndFillElement*>(item)->index();
- break;
- default:
- item->draw(&painter,len>item->length()?1:len/item->length());
- break;
- }
-
- //len不够就是还没画完,后面的就不画了
- if(len<item->length())
- break;
- progress_temp+=item->length();
- }
- drawEnd=bool(i>=dataList.count()&&progress_temp>=dataLength);
- }
-
- void MyPainter::start()
- {
- timer->start(timerInterval);
- drawLength=0;
- drawEndIndex=-1;
- drawEnd=false;
- startTime=QTime::currentTime();
- }
-
- void MyPainter::begin(const QPointF &pos)
- {
- //begin为路径规划开始,状态复位
- currentPos=pos;
- dataLength=0;
- dataList.clear();
- }
-
- void MyPainter::end()
- {
- //end暂无操作
- }
-
- void MyPainter::setPenColor(const QColor &color)
- {
- PenColorElement *ele=new PenColorElement(color);
- dataList.push_back(ele);
- }
-
- void MyPainter::setPenWidth(int width)
- {
- PenWidthElement *ele=new PenWidthElement(width);
- dataList.push_back(ele);
- }
-
- void MyPainter::beginFill(const QColor &color)
- {
- //开始填充后,beginElement!=null,path在别的函数判断中就能追加路径
- fillBeginIndex++;
- fillBeginPath=QPainterPath();
- fillBeginPath.moveTo(currentPos);
- fillBeginElement=new BeginFillElement(fillBeginIndex,color);
- dataList.push_back(fillBeginElement);
- }
-
- void MyPainter::endFill()
- {
- if(fillBeginElement){
- //end后路径就完成了
- fillBeginElement->setFillPath(fillBeginPath);
- EndFillElement *ele=new EndFillElement(fillBeginIndex);
- dataList.push_back(ele);
-
- fillBeginElement=nullptr;
- }
- }
-
- void MyPainter::moveTo(const QPointF &pos)
- {
- if(fillBeginElement){
- fillBeginPath.moveTo(pos);
- }
- currentPos=pos;
- }
-
- void MyPainter::lineTo(const QPointF &pos)
- {
- if(fillBeginElement){
- fillBeginPath.lineTo(pos);
- }
- LineElement *ele=new LineElement(QLineF(currentPos,pos));
- dataList.push_back(ele);
- dataLength+=ele->length();
- currentPos=pos;
- }
-
- void MyPainter::arc(const QPointF ¢er, int radius, int startAngle, int spanAngle)
- {
- QRectF ele_rect=QRectF(center.x()-radius,center.y()-radius,
- radius*2,radius*2);
- if(fillBeginElement){
- //const int len=std::ceil(std::abs(spanAngle)*M_PI*radius/180.0);
- fillBeginPath.arcTo(ele_rect,startAngle,spanAngle);
- }
- ArcElement *ele=new ArcElement(ele_rect,startAngle,spanAngle);
- dataList.push_back(ele);
- dataLength+=ele->length();
- //currentPos=stop;
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。