问题
I've created a Qt project which displays a circle on a widget. Then I have a method which redraws the circle at different positions every time I call the method. What I want is to run that method in a for loop, say ten times, and be shown each of the 10 positions that the circle is redrawn in every one second.
Something along the lines of:
void method::paintEvent(QPaintEvent * p)
{
//code
for(int i=0; i<10;i++)//do this every second
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter); //using QPainter
}
//code
}
I've read about QTimer, but do not know how to use it. And the sleep function does not work.
回答1:
All you need to do is to trigger an update()
from the timer event. The update()
method schedules a paintEvent
on the widget.
It is invalid to paint on a widget outside of the paintEvent
- that's the mistake that all other answers did at the time I posted this answer. Merely calling the paintEvent
method is not a workaround. You should call update()
. Calling repaint()
would also work, but do so only when you have understood the difference from update()
and have a very good reason for doing so.
class Circle;
class MyWidget : public QWidget {
Q_OBJECT
QBasicTimer m_timer;
QList<Circle> m_circles;
void method(Circle &);
void paintEvent(QPaintEvent * p) {
QPainter painter(this);
// WARNING: this method can be called at any time
// If you're basing animations on passage of time,
// use a QElapsedTimer to find out how much time has
// passed since the last repaint, and advance the animation
// based on that.
...
for(int i=0; i<10;i++)
{
method(m_circles[i]); //co-ordinates change
m_circles[i].paint(&painter);
}
...
}
void timerEvent(QTimerEvent * ev) {
if (ev->timerId() != m_timer.timerId()) {
QWidget::timerEvent(ev);
return;
}
update();
}
public:
MyWidget(QWidget*parent = 0) : QWidget(parent) {
...
m_timer.start(1000, this);
}
};
回答2:
As you've guessed, QTimer is the correct mechanism to use here. How to go about setting it up?
Here's one option:
class MyClass : public QObject
{
public:
MyClass():i(0)
{
QTimer::singleShot(1000,this,SLOT(callback()));//or call callback() directly here
} //constructor
protected:
unsigned int i;
void paintEvent(QPaintEvent * p)
{
//do your painting here
}
public slots:
void callback()
{
method(circle[i]); //co-ordinates change
//circle[i].pain( & painter); //don't use QPainter here - call update instead
update();
++i;//increment counter
if(i<10) QTimer::singleShot(1000,this,SLOT(callback()));
}
}
回答3:
Try something like this:
class MyDrawer : public QObject
{
Q_OBJECT
int counter;
QTimer* timer;
public:
MyDrawer() : QObject(), counter(10)
{
timer = new QTimer(this);
connect(timer, SIGNAL(timeout()), this, SLOT(redraw()));
timer->start(1000);
}
public slots:
void redraw()
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter);
--counter;
if (counter == 0) timer->stop();
}
};
Don't forget to run moc
on this file, although if your class is a QObject you probably already do it.
回答4:
Try this.
for(int i=0; i<10;i++)//do this every second
{
method(circle[i]); //co-ordinates change
circle[i].pain( & painter);
sleep(1000);// you can also use delay(1000);
}
Use sleep() The function called sleep(int ms) declared in which makes the program wait for the time in milliseconds specified.
来源:https://stackoverflow.com/questions/23091664/qt-how-to-loop-a-method-every-second-c