Производительность QGraphicsScene / QGraphicsView - PullRequest
4 голосов
/ 14 февраля 2011

Я использую пару QGraphicsScene / QGraphicsView в моем проекте У меня проблема с производительностью этой пары. Я добавил свои пользовательские графические элементы в сцену и отобразил содержимое в представлении. После этого мой метод рисования пользовательских графических элементов непрерывно вызывается по сцене (как бесконечный цикл). Это составляет% 25 загрузки процессора (приблизительно 400 элементов на сцене). Что может вызвать это поведение?

Вот одна из моих реализаций:

class LevelCrossingItem : public QGraphicsWidget
{
public:
    LevelCrossingItem(QString _id,qreal _x,qreal _y);
    ~LevelCrossingItem();
    QRectF boundingRect() const;
    QSizeF sizeHint(Qt::SizeHint which, const QSizeF &constraint  = QSizeF()) const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget /* = 0 */);
    void readStateBits();
    bool isClosed();
    bool isGateArmBroken();
    bool isOpenedDuringRouteTanzimCompleted();
    bool hasDataConsistencyWarning();
    int type() const {return Type;}
private slots:
    void setVisible(bool);
private:
    enum {Type = FIELDLEVELCROSSING};
    QString m_id;
    QString m_source;
    short m_closedState;
    short m_brokenGateArmState;
    short m_openedDuringRouteTanzimCompletedState;
    short m_dataConsistencyWarningState;
    QBitArray stateBitArray;
    qreal x,y;
    QSvgRenderer *renderer;
};  

#include "levelcrossing.h"

LevelCrossingItem::LevelCrossingItem(QString _id,qreal _x,qreal _y):m_id(_id),x(_x),y(_y),stateBitArray(4)
{
    m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
    renderer = new QSvgRenderer;
    setStateArray(stateBitArray);
    setZValue(-0.5);
}

LevelCrossingItem::~LevelCrossingItem()
{
    delete renderer;
}

void LevelCrossingItem::setVisible(bool visible)
{
    QGraphicsItem::setVisible(visible);
}

QRectF LevelCrossingItem::boundingRect() const
{
    return QRectF(QPointF(x,y),sizeHint(Qt::PreferredSize));
}

QSizeF LevelCrossingItem::sizeHint(Qt::SizeHint which, const QSizeF &constraint) const
{
    return QSizeF(50,270);
}

void LevelCrossingItem::readStateBits()
{
    m_closedState = property("Closed").toInt();
    m_brokenGateArmState = property("Broken").toInt();
    m_openedDuringRouteTanzimCompletedState = property("OpenedOnRouteWarning").toInt();
    m_dataConsistencyWarningState = property("DataConsistencyWarning").toInt();

    stateBitArray.setBit(0,qvariant_cast<bool>(m_closedState));
    stateBitArray.setBit(1,qvariant_cast<bool>(m_brokenGateArmState));
    stateBitArray.setBit(2,qvariant_cast<bool>(m_openedDuringRouteTanzimCompletedState));
    stateBitArray.setBit(3,qvariant_cast<bool>(m_dataConsistencyWarningState));

    setStateArray(stateBitArray);
}

void LevelCrossingItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget )
{
    Q_UNUSED(option);
    Q_UNUSED(widget);

    readStateBits();

    m_closedState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("closed")
        : m_source = LEVELCROSSING_RESOURCE_PATH.arg("open");
    m_brokenGateArmState == Positive ? m_source = LEVELCROSSING_RESOURCE_PATH.arg("broken")
        : m_source = m_source;

    if(m_openedDuringRouteTanzimCompletedState == Positive)
    {
        setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),true);
        if(stateChanged())
            emit itemAlarmOccured(m_id,LevelCrossingIsOpenDuringTanzimCompleted);
    }
    else
         setWarningVisible(OOR_WRN.arg(name()).arg(interlockingRegionId()),false);

    if(m_dataConsistencyWarningState == Positive)
    {   
        setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),true);
        if(stateChanged())
            emit itemAlarmOccured(m_id,LevelCrossingDataConsistency);
    }
    else
        setWarningVisible(DC_WRN.arg(name()).arg(interlockingRegionId()),false);

    renderer->load(m_source);
    renderer->render(painter,boundingRect());
}

bool LevelCrossingItem::isClosed()
{
    return m_closedState == Positive;
}

bool LevelCrossingItem::isGateArmBroken()
{
    return m_brokenGateArmState == Positive;
}

bool LevelCrossingItem::isOpenedDuringRouteTanzimCompleted()
{
    return m_openedDuringRouteTanzimCompletedState == Positive;
}

bool LevelCrossingItem::hasDataConsistencyWarning()
{
    return m_dataConsistencyWarningState == Positive;
}

Я читаю координаты x и y из файла xml. Для этого элемента координаты x и y равны 239 344

соответственно

1 Ответ

4 голосов
/ 14 февраля 2011

Скорее всего, ваш графический элемент имеет ошибки в реализации. У меня было похожее поведение, но я не мог понять, что именно вызывает его. Я подозреваю, что это происходит, когда вы рисуете за пределами прямоугольника. Это вызывает некоторую процедуру очистки, которая, в свою очередь, вызывает перерисовку элемента, и здесь начинается цикл. В конце концов я решил проблему, тщательно проверив реализацию моего пользовательского графического элемента и убедившись, что:

  1. Это не картина вне MyGraphicsItem::boundingRect. Используйте painter->setClipRect(boundingRect())
  2. MyGraphicsItem::shape не пересекается с MyGraphicsItem::boundingRect.
  3. Если вы переопределяете любые другие функции QGraphicsItem, убедитесь, что ваша реализация верна.

Надеюсь, это поможет. Не стесняйтесь размещать исходный код вашего графического элемента, вам будет легче найти проблему.

...