Solved Algorithm animation(QPainter)
-
I have a red rectangle and after 5 sec it becomes blue during run time?
One way would be with a timer:
QGraphicsRectItem* rectangle = ... //get it from somewhere QTimer::singleShot(5000, [=]{ rectangle->setBrush(Qt::blue); });
-
@Chris-Kawa said:
QTimer::singleShot(5000, [=]{ rectangle->setBrush(Qt::blue); });
MOTHER OF GOD! Thank you so much now I can continue with the app :-)
-
@Chris-Kawa Ok, got a little bit stuck again how I can update the scene view. For example I found that one rectangle is bigger than the other one how I can animate the swap. I have a list of pointers to the rectangles, after I swapped the pointers in the list, how I can repaint the GraphicsView with the new pointers?
-
one rectangle is bigger than the other one how I can animate the swap
Sorry, I can't make sense of what you're asking. What swap? What does a rectangle size have to do with it?
after I swapped the pointers in the list, how I can repaint the GraphicsView with the new pointers?
Again this makes no sense. Moving a pointer in a list has nothing to do with graphics view. Do you mean you want to move the rectangle in the scene or what? A pointer to a graphics item has nothing to do with its position on the scene.
What are you trying to do exactly? I mean conceptually.
-
@Chris-Kawa I thought I could repaint the new List which contains the pointers. I want to swap two rectangles. The first one is = 3(height) the second one is = 2; I want to swap them, so that on the first position would be rectangle number two with the height of 2, and on the second position would rectangle number one with height = 3. But I want it to swap with some pause, so I could see it, smth like a timer.
-
You don't need to repaint anything manually. You just change the position of the item in the scene and it will refresh the view automatically. To animate the move you can use a QGraphicsItemAnimation.
Here's a simple example:
void moveItemTo(QGraphicsItem* item, const QPointF& endPoint) { QTimeLine* t= new QTimeLine(2000); t->setEasingCurve(QEasingCurve::InOutCubic); QObject::connect(t, &QTimeLine::finished, t, &QTimeLine::deleteLater); QGraphicsItemAnimation* a = new QGraphicsItemAnimation(t); a->setTimeLine(t); a->setItem(item); a->setPosAt(0.0, item->pos()); a->setPosAt(1.0, endPoint); timeLine->start(); }
-
@Chris-Kawa I'll give it a try. Thank you a lot. And the last question, for sure, How I can emit a SingleShot every second in a loop, because
for(int i=0;i<random_numbers_.size()-1;i++){
for(int j=0;j<random_numbers_.size()-1;j++){
QTimer::singleShot(1000, [=]{ rectan[i]->setBrush(Qt::green); });
}
During the executing, after a second it makes every rectangle till the 9-th green, it loops and SingleShots every second in a loop. But how I can do this with a pause, liek: The first one is green, after a second the second becomes green, so I could see it?
} -
for(int i = 0; i < random_numbers_.size(); ++i) { QTimer::singleShot(1000 + i * 1000, [=]{ rectan[i]->setBrush(Qt::green); }); }
-
@Chris-Kawa I thought about that but is there a way that SingleShot won't be chained by time, because In the future I will need to set the second one green and the first one red, So it'l look like that the rectangle is crawling till the end
-
Ok, I think you're going deeper and deeper into the woods but it's a totally bad direction.
So if I'm getting this right you are making some algorithm that does stuff (sorting?) to some items represented by rectangles and you want to visualize the steps. Is that right?
In that case setting up hardcoded timers and single shots is going against the wind because you're effectively tying to predict the whole thing and set timers for it. That's just gonna give you a headache and you won't know what you did the next day.Step back and look at the problem. You've got some algorithm that operates on an array. Conceptually:
while(!done()) { doAnotherStep(); }
Now you want to visualize the steps, conceptually:
while(!done()) { doAnotherStep(); visualizeTheStep(); }
The problem is that the visualization should take time, so this approach is not gonna work. What you need to do is make it event driven, i.e. conceptually:
stepEnded -> visualize visualizationEnded -> done ? exit : doAnotherStep
For this you can use the signal/slot mechanism of Qt. Make a class that does the algorithm and has a step method. At the end of the method emit a signal. Make another class for visualization and give it a visualize method. At the end of it emit a signal. Then just connect the two.
Rough concept:
class Algo : public QObject { Q_OBJECT public: Algo(Vector<stuff>* data) : dataPtr(data) {} bool done() { return /* check if more steps needed */ } void doStep() { /* do stuff to dataPtr */; emit stepFinished(someStuffToSwap, someOtherStuffToSwap); } signal: void stepFinished(stuff* item1, stuff* item2); private: Vector<stuff>* dataPtr; }; class Vis : public QObject { Q_OBJECT public: Vis(Vector<stuff>* data) { /*create graphics items and whatnot */ } void visualizeStep(stuff* item1, stuff* item2) { /* do the animations here and emit finished() when they're done*/ } signals: void finished(); }; //and then you can use it like this: Vector<stuff> data = ... Algo algo(&data); Vis vis(&data); connect(algo, &Algo::stepFinished, vis, &Vis::visualizeStep); connect(vis, &Vis::finished(), [&]{ if(!algo.done()) algo.doStep(); }); algo.doStep(); /start the first step