Сон внутри цикла, который использует Paintevent в QT C++
По сути, я хочу нарисовать прямоугольники для каждого числа в моем списке. Чем больше число, тем больше прямоугольник. Моя проблема в том, когда я действительно хочу сделать это, шаг за шагом, и ждать несколько секунд между каждым рисунком. Я искал несколько решений, но я не могу заставить их работать для этого конкретного случая. Я видел, что могу использовать fflush для освобождения всего, что находится в буфере, но я не знаю, как я могу использовать это для этого.
QPainter painter(this);
painter.setRenderHint(QPainter::Antialiasing, true);
painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
int weight=300/lista.size;
int posx=weight;
for (int i=1; i<=lista.size; i++){
List_node * node = list.get_element_at(i);
int num=node->getValue(); //this returns the value of the node
if (i==3){
painter.setBrush(QBrush(Qt::red, Qt::SolidPattern)); // this line is to draw a rectangle with a different color. Testing purposes.
}
painter.drawRect(posx,400-(num*10),weight,num*10);
sleep(1); //this sleep isn't working correctly.
painter.setBrush(QBrush(Qt::green, Qt::SolidPattern));
posx+=weight;
}
Любая помощь могла бы быть полезна.
1 ответ
sleep() не будет работать для этого - он блокирует цикл событий Qt и не дает Qt выполнять свою работу, пока он спит.
Вам нужно сохранить одну или несколько переменных-членов, чтобы запомнить текущее состояние изображения, которое вы хотите нарисовать, и реализовать paintEvent() для рисования только этого текущего отдельного изображения. paintEvent() (как и любая функция, выполняемая в потоке GUI Qt) всегда должен возвращаться немедленно и никогда не спать и не блокироваться.
Затем, чтобы реализовать анимационную часть, настройте объект QTimer, чтобы он вызывал для вас слот через регулярные промежутки времени (например, один раз каждые 1000 мс или как вам часто угодно). Реализуйте этот слот, чтобы настроить ваши переменные-члены на их следующее состояние в последовательности анимации (например, rectangle_size++ или что-то еще), а затем вызовите update() для вашего виджета. update() скажет Qt снова вызвать paintEvent() для вашего виджета как можно скорее, поэтому ваше отображение будет обновлено до следующего кадра очень скоро после того, как ваш метод слота вернется.
Ниже приведен тривиальный пример техники; при запуске он показывает красный прямоугольник, становящийся все больше и меньше:
// begin demo.h
#include <QWidget>
#include <QTimer>
class DemoObj : public QWidget
{
Q_OBJECT
public:
DemoObj();
virtual void paintEvent(QPaintEvent * e);
public slots:
void AdvanceState();
private:
QTimer _timer;
int _rectSize;
int _growthDirection;
};
// begin demo.cpp
#include <QApplication>
#include <QPainter>
#include "demo.h"
DemoObj :: DemoObj() : _rectSize(10), _growthDirection(1)
{
connect(&_timer, SIGNAL(timeout()), this, SLOT(AdvanceState()));
_timer.start(100); // 100 milliseconds delay per frame. You might want to put 2000 here instead
}
void DemoObj :: paintEvent(QPaintEvent * e)
{
QPainter p(this);
p.fillRect(rect(), Qt::white);
QRect r((width()/2)-_rectSize, (height()/2)-_rectSize, (_rectSize*2), (_rectSize*2));
p.fillRect(r, Qt::red);
}
void DemoObj :: AdvanceState()
{
_rectSize += _growthDirection;
if (_rectSize > 50) _growthDirection = -1;
if (_rectSize < 10) _growthDirection = 1;
update();
}
int main(int argc, char ** argv)
{
QApplication app(argc, argv);
DemoObj obj;
obj.resize(150, 150);
obj.show();
return app.exec();
}