Как поднять производительность обновления сцены QGraphicsScene?
Написал вот такой код:
.h
#ifndef STATEBALANSER_H
#define STATEBALANSER_H
#include <QGraphicsRectItem>
#include <QPainter>
#include <memorymap.h>
class StateBalanser : public QGraphicsRectItem
{
public:
StateBalanser(int num);
void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);
void StateBalance();
void setColorState(unsigned char value_1, unsigned char value_2);
void setColorText(QColor text);
void setFontText(QFont fontText);
private:
unsigned char colorState;
unsigned char colorMode;
int number;
QRectF _intersect;
QColor _fillColorState;
QColor _fillColorModeWork;
QColor _fillColorText;
QFont _fontText;
public:
QRectF boundingRect() const;
QPainterPath shape() const;
};
#endif // STATEBALANSER_H
.cpp
#include "statebalanser.h"
StateBalanser::StateBalanser(int num) :
number(num)
{
setColorState(10,10); // 10 10
setAcceptHoverEvents(true);
StateBalanser::StateBalance();
StateBalanser::setColorText(Qt::black);
StateBalanser::setFontText(QFont("Monospace", 10));
setToolTip(QString("Sensor %1").arg(number + 1));
}
void StateBalanser::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
{
painter->fillRect(boundingRect(), _fillColorModeWork);
painter->fillRect(_intersect, _fillColorState);
painter->drawPath(shape());
painter->setFont(_fontText);
painter->setPen(_fillColorText);
painter->drawText(boundingRect(), Qt::AlignCenter, QString("%1").arg(number + 1) );
}
void StateBalanser::StateBalance()
{
_intersect = boundingRect().intersected(QRectF(3, 3, 44, 32));
}
void StateBalanser::setColorState(unsigned char value_1, unsigned char value_2)
{
switch(value_2)
{
case StopBalancer : _fillColorModeWork = QColor("#000000") ;
break;
case ChargeBalancer : _fillColorModeWork = QColor("#0000ff") ;
break;
case DischargeBalancer : _fillColorModeWork = QColor("#ff0000") ;
break;
case EsrBalancer : _fillColorModeWork = QColor("#32CD32") ;
break;
case DisconnectBalancer : _fillColorModeWork = QColor("#000000") ;
break;
default : _fillColorModeWork = QColor("#ffffff") ;
break;
}
switch(value_1)
{
case StateGood : _fillColorState = QColor("#99FF99") ;
break;
case StateFiftyFifty: _fillColorState = QColor("#FFFF66") ;
break;
case StateFault : _fillColorState = QColor("#FF9999") ;
break;
case StateDisconnect: _fillColorState = QColor("#999999") ;
break;
default : _fillColorState = QColor("#ffffff") ;
break;
}
}
void StateBalanser::setColorText(QColor text)
{
_fillColorText = QColor(text);
}
void StateBalanser::setFontText(QFont fontText)
{
_fontText = fontText;
}
QRectF StateBalanser::boundingRect() const
{
return QRectF(0, 0, 49, 37);
}
QPainterPath StateBalanser::shape() const
{
QPainterPath path;
path.addRect(boundingRect());
return path;
}
В конструкторе mainwindow :
graphicsScene = new QGraphicsScene(this);
for (int i = 0; i < 256; i++) {
statebalanser = new StateBalanser(i);
statebalanser->setPos((i * 54) % 540, (i / 10) * 42);
graphicsScene->addItem(statebalanser);
}
ui->graphicsView->setAlignment(Qt::AlignLeft);
ui->graphicsView->setScene(graphicsScene);
Делаю обновление :
QList<QGraphicsItem *> items = graphicsScene->items(Qt::AscendingOrder);
for (int i = 0; i < items.size(); i++) {
dynamic_cast<StateBalanser*>(items.at(i))->setColorState(massifDataBalansir[i].State, massifDataBalansir[i].modeWork);
}
graphicsScene->update();
items.clear();
Проблема в долгом обновление. Занимает пример 400 мс. при загрузки процессора на 100% период обновления 1 секунда. Как можно ускорить обновление ? Или выводить не все сразу объекты а по одному или несколько?
Ответы (1 шт):
В первую очередь и самое главное, что сразу бросается в глаза это вот:
painter->fillRect(boundingRect().intersected(QRectF(3, 3, 44, 32)), fillColor);
Поиск пересечения двух прямоугольников это довольно "тяжелая" операция. Заведите переменную, отвечающую за пересечение и вычисляйте ее где-нибудь в другом месте, вне метода отрисовки. Сейчас это, например, в конструкторе, но если вы будете менять положение item-ма, то в методе изменения положения:
class StateBalanser ... {
public:
StateBalance() {
_intersect = boundingRect().intersected(QRectF(3, 3, 44, 32));
}
void paint(...) {
painter->fillRect(_intersect, fillColor);
}
private:
QRect _intersect;
QColor _fillColorState;
QColor _fillColorMode;
}
Второе, выбор цвета (оба свича) перенесете туда, где вы этот цвет устанавливаете, - нет никакой необходимости постоянно делать выбор в paint. Метод setColorState:
void StateBalanser::setColorState(unsigned char value_1, unsigned char value_2)
{
switch(value_2)
{
case StopBalancer : _fillColorMode = QColor("#000000") ;
break;
case ChargeBalancer : _fillColorMode = QColor("#0000ff") ;
break;
case DischargeBalancer : _fillColorMode = QColor("#ff0000") ;
break;
case EsrBalancer : _fillColorMode = QColor("#32CD32") ;
break;
case DisconnectBalancer : _fillColorMode = QColor("#000000") ;
break;
default : _fillColorMode = QColor("#ffffff") ;
}
// Для _fillColorState аналогично
}