Last active
April 1, 2017 04:26
-
-
Save docsteer/64483cc8f44ca53565912c50d11cf4a9 to your computer and use it in GitHub Desktop.
Solution for Stack Overflow Question 43147889 "Bowl Draining" effect in Qt
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#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