2010-02-25 3 views
1

Я изучаю и модифицирую пример fridge magnets, и последнее, что я пытался сделать, это нарисовать несколько меток и линий, которые должны быть на заднем плане.QWidget's paintEvent() lagging application

Осмотревшись, пытаясь понять, как рисовать метки и линии, я узнал, что могу переопределить paintEvent() QWidget, чтобы сделать это. После того, как я это сделал, приложение получило лагги, и я узнал, что это потому, что paintEvent() вызывается в бесконечно замкнутом цикле.

Попытка выяснить, как это исправить, я переместил код, который нарисовал метки и строки для конструктора класса. Тем не менее, только ярлыки были нанесены на приложение. После этого я оставил ярлыки в конструкторе, но переместил код, который нарисовал строки, чтобы рисоватьEvent(). Он работал, линии были нарисованы так, как ожидалось, и paintEvent() вызывается только при перетаскивании материала вокруг.

Почему строки не были нарисованы на конструкторе и почему paintEvent() попал в бесконечный цикл?

Вот фрагмент кода, который должен нарисовать этикетки и линии:

QPen pen(Qt::lightGray, 0, Qt::SolidLine, Qt::SquareCap, Qt::RoundJoin); 
QPainter paint(this); 
paint.setPen(pen); 
int scale = 20; 
for(int x=0; x<25; x++){ 
    QString timetext= "0"+QString::number(x)+":00"; 
    QLabel *time= new QLabel(timetext,this); 
    time->move(x*scale,2); 
    time->show(); 
    paint.drawLine(x*scale,12,x*scale,400); 
} 

ответ

9

Вы добавляете объекты в виджет Дерево во paintEvent(). Это считается неудачным. Планировщик Qt для повреждения & рисунок увидит, что новый ребенок должен быть нарисован и попытаться справиться с этим, и, скорее всего, это результат цикла. Если вы переопределите paintEvent(), сделайте всю картину в одном и том же объекте! Золотое правило: paintEvent() только для покраски! Не для создания объектов или чего-либо еще.

Делают это так:

QFont font(painter.font()); 
font.setBold(true); 
painter.setFont(font); 
painter.fillRect(rect(), Qt::black); 
painter.setPen(Qt::white); 
painter.drawText(rect(), Qt::AlignCenter, tr("White text on dark background. Awesome.")); 
+0

Должен ли я переместить весь код рисования из конструктора и в paintEvent? –

+1

Да, рисунок должен выполняться только в paintEvent(). Или вы можете нарисовать QPixmap, который является фоном виджета (чаще всего QLabel). Затем вы будете рисовать только один раз (через некоторое время), не касаясь самой paintEvent(). Это зависит от вашего приложения. Обратите внимание, что (повторное) выполнение рисования в paintEvent() не так дорого, как можно было бы подумать. В большинстве случаев Qt использует двойную буферизацию, поэтому просто перемещение окон вокруг не приведет к paintEvent(). С другой стороны, например, на удаленных сеансах двойная буферизация не действует. – ypnos

2

Почему линии не нарисованы на конструктор?

Я думаю, что они были, но они были «удалены» при следующем вызове к paintEvent(), в котором вы не рисовать линии больше ...

Почему paintEvent() попал в бесконечный цикл?

Я думаю, это может быть связано с вашим временем-> show(); который называется 25 раз каждый раз, когда paintEvent вызывается ... Я не уверен в этом, но, поскольку время как виджет как родитель, когда вы вызываете «show», возможно, он вызывает «show» на своем родителе, поэтому запускает paintEvent. ... Вы знаете, что я имею в виду ...

Так, Ypnos дал вам решение, я обращаюсь к нему :)