Как переместить около 1000 элементов в QGraphicsScene, не блокируя пользовательский интерфейс



У меня есть около 1000 графических элементов в моем QGraphicsScene. Я хочу переместить все эти 1000 пунктов на новое место. Новые позиции не связаны друг с другом, и все они должны быть сделаны одновременно.

Один из способов-перебрать эти 1000 элементов и вызвать setPos для каждого из них ! Я думаю, что это заблокирует пользовательский интерфейс. Другой способ-нарисовать изображение в другом потоке и установить это изображение в результате в QGraphicsScene!

Может быть, у вас есть другая идея.Я с нетерпением жду этого !

892   3  

3 ответов:

Qt drawing может быть очень быстрым, если вы понимаете, как это работает, даже если вы хотите нарисовать, например, 1000 рыб, все движущиеся независимо.

В случае большого количества элементов худший способ справиться с этим-создать отдельный QGraphicsItem / QGraphicsObject для каждого элемента и попытаться переместить и нарисовать их все независимо. Одна из главных проблем, которую люди здесь не понимают, заключается в том, что когда краска(QPainter * painter...) функция называется, они устанавливают перо и кисть на живописца. Обычно это нормально, но есть накладные расходы, делающие это как внутренне, графический конвейер будет остановлен. На 1000 пунктов, что на самом деле происходит, чтобы замедлить вещи вниз.

Вместо этого, если мы проектируем рыбу как косяк рыб и создаем только один QGraphicsItem, мы можем отслеживать их положение внутри и вызывать функцию paint только один раз.

class SchoolOfFish : QGraphicsObject // QGraphicsObject for signals / slots
{
    Q_OBJECT

    public:
        void UpdateFish();

    protected:
        void paint(QPainter* painter, const QStyleOptionGraphicsItem* option, QWidget* widget = 0); // overloaded paint function      

    private:
        QList<QPoint> m_fishPositionList;
};

Обратите внимание, что все позиции рыб хранятся в QList объектов QPoint. Есть несколько оптимизаций, которые могут все будет сделано здесь. Во-первых, я часто вижу, как люди обновляют позиции элементов в функции paint, что приводит к низкой производительности; в paint должна быть реализована только функциональность рисования.

Обновление позиций рыбы может быть первоначально сделано по таймеру, возможно, стремясь к 30 кадрам в секунду. Если это слишком медленно, то мы могли бы создать отдельный поток, который обновляет все позиции рыб и выдает список обратно в объект SchoolOfFish; все графические рендеринги должны быть выполнены на основном нитка.

Этот метод на самом деле просто рассматривает косяк рыб как систему частиц . После разработки системы таким образом, если потребуется, последняя оптимизация, которую я хотел бы сделать, будет переход на OpenGl. Однако обратите внимание, что вы можете фактически получить стандартные вызовы Qt paint для использования OpenGl в качестве документов состояния QWidget

Для визуализации с помощью OpenGL просто вызовите setViewport (new QGLWidget). QGraphicsView становится владельцем виджета viewport.

Для рисования большого количества элементов в Qt вам лучше будет перейти к интерфейсу рисования более низкого уровня. OpenGL, например, может быть реализован на QWindow (который может быть привязан к вашему главному окну), см. http://qt-project.org/doc/qt-5.0/qtgui/openglwindow.html . OpenGL может быть немного болезненным, но вам не придется беспокоиться о блокировке, мой текущий проект делает именно это, чтобы вывести 300 000 цветных квадратов примерно за 100 мс.

Существенное ускорение setPos() в динамических сценах может быть достигнуто с помощью:

QGraphicsScene scene;
scene.setItemIndexMethod(QGraphicsScene.NoIndex);
Это намного быстрее, чем по умолчанию QGraphicsScene.BspTreeIndex для динамических сцен, но стоит дорого, так как события, которые должны запрашивать QGraphicsScene, теперь будут значительно медленнее (например, события наведения). Другой способ ускорить процесс-уменьшить общее количество объектов. Если сцена использует много QGraphicsItemGroup, можно попытаться заменить их простым QGraphicsItem и переопределить его метод paint() вместо использования дочернего объекты. Тем не менее, даже при такой оптимизации я нахожу производительность QGraphicsScene все еще довольно жалкой, как только вы выходите за пределы нескольких сотен объектов. QtQuick, похоже, гораздо лучше справляется с большими коллекциями объектов.

Comments

    Ничего не найдено.