Skip to content

Instantly share code, notes, and snippets.

@docsteer
Last active April 1, 2017 04:26
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save docsteer/64483cc8f44ca53565912c50d11cf4a9 to your computer and use it in GitHub Desktop.
Save docsteer/64483cc8f44ca53565912c50d11cf4a9 to your computer and use it in GitHub Desktop.
Solution for Stack Overflow Question 43147889 "Bowl Draining" effect in Qt
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QAbstractScrollArea>
#include <Qt>
#include <QtMath>
#include <QTimer>
#include <QLineF>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
scene = new QGraphicsScene(this);
view = ui->graphicsView;
view->setScene(scene);
view->setSceneRect(0,0,512,512);
viewSize = view->width() /2;
sceneCenter = QPointF(viewSize,viewSize);
draw_Radius = 200;
connect(ui->dial, &QDial::valueChanged, this, &MainWindow::slt_updateAngleFromDial);
//add green indicator line
green_line = QLineF(QPointF(draw_Radius, 0), QPointF(draw_Radius + 20, 0));
QPen greenPen(Qt::green, Qt::SolidLine);
greenPen.setWidth(3);
green_needle = scene->addLine(green_line, greenPen);
green_needle->setTransformOriginPoint(QPointF(0,0));
//draw static outer circle
int mSize = draw_Radius *2;
QRectF rimCircle(0, 0, mSize, mSize);
// Center about 0,0
rimCircle.moveCenter(QPointF(0,0));
mCircle = new QGraphicsEllipseItem(rimCircle);
QBrush rimTip(Qt::darkCyan, Qt::NoBrush);
QPen rimPen(Qt::darkCyan, Qt::SolidLine);
mCircle->setBrush(rimTip);
mCircle->setPen(rimPen);
scene->addItem(mCircle);
//draw static inner circle
int cSize = 3;
QRectF circ(0, 0, cSize,cSize);
circ.moveCenter(QPointF(0,0));
cCircle = new QGraphicsEllipseItem(circ);
QBrush rimTip2(Qt::black, Qt::SolidPattern);
QPen rimPen2(Qt::black, Qt::SolidLine);
cCircle->setBrush(rimTip2);
cCircle->setPen(rimPen2);
scene->addItem(cCircle);
// Polyline path
m_pathItem = new QGraphicsPathItem();
scene->addItem(m_pathItem);
view->centerOn(0,0);
startDrainTheBowl_Timer();
}
MainWindow::~MainWindow(){delete ui;}
void MainWindow::slt_updateAngleFromDial(int angle){
draw_angle = angle;
green_needle->setRotation(draw_angle);
}
void MainWindow::startDrainTheBowl_Timer(){
QTimer* drainTimer = new QTimer(this);
connect(drainTimer, SIGNAL(timeout()), this, SLOT(slt_drainTheBowl()));
drainTimer->start(100);
}
void MainWindow::slt_drainTheBowl()
{
// Move the points towards center
QMutableListIterator<QPointF> i(m_points);
while(i.hasNext())
{
i.next();
QLineF line(QPointF(0,0), i.value());
// We move a point by decreasing the length from the origin to the point by 1
qreal length = line.length();
length -=1;
line.setLength(length);
// If the point is now at (or past) the origin, remove from the list
if(length<=0)
{
i.remove();
}
else
{
// Update the point in the list
i.setValue(line.p2());
}
}
// Add a new point to the list based on the current angle
QPointF newPoint;
newPoint.setY( qSin(qDegreesToRadians((double)draw_angle)) * 200 );
newPoint.setX( qCos(qDegreesToRadians((double)draw_angle)) * 200 );
// Set the points into the path item
QPainterPath path;
path.moveTo(newPoint);
for(int i=0; i<m_points.count(); i++)
path.lineTo(m_points[i]);
m_points << newPoint;
m_pathItem->setPath(path);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment