Производительность QGraphicsPixmapItem::setPixmap()?

Поскольку кажется, что мне нужно улучшить производительность моего кода, я хотел спросить, насколько хороша производительность QGraphicsPixmapItem::setPixmap(*Qimage)? Мое изображение имеет размер 1024x1024 пикселей и обновляется примерно каждые 2,5 секунды. Но мне нужно, чтобы он обновлялся намного быстрее (4096x каждые 2,5 секунды в лучшем случае). Возможно ли это с QGraphicsPixmapItem::setPixmap(*Qimage)? Я заполняю каждый пиксель QImage напрямую массивом: array[y*SCENEWIDTH+x] = color.

Но с такой скоростью QGraphicsPixmapItem::setPixmap(*Qimage), кажется, замораживает мой графический интерфейс. Цель состоит в том, чтобы отображать огромное количество данных, поступающих в полярных координатах (азимут за азимутом) (радарное видео).

Какие-либо предложения? Благодарю вас!


person honiahaka10    schedule 18.11.2015    source источник
comment
Но мне нужно, чтобы он обновлялся намного быстрее (в лучшем случае 4096x каждые 2,5 секунды).. 4096 / 2,5 = 1638 раз в секунду. Вам нужно всего 60 кадров в секунду для плавных графических переходов, так почему вы считаете, что вам нужно так быстро обновлять изображение?   -  person TheDarkKnight    schedule 18.11.2015
comment
@TheDarkKnight Возможно, он имеет в виду, что изображение размером 4096x4096 должно обновляться каждые 2,5 секунды.   -  person thuga    schedule 18.11.2015
comment
@TheDarkKnight Я тоже думал об этом, ну, 4096 был бы идеальным. Хорошо, я согласен с вами, что мне нужно только 60 кадров в секунду (а может быть, и немного больше), но даже при гораздо более низкой скорости (около 5 кадров в секунду) мой графический интерфейс становится довольно медленным и ненадолго зависает. Когда я удаляю только QGraphicsPixmapItem::setPixmap(*Qimage), все работает отлично, поэтому я думаю, что проблема должна быть здесь.   -  person honiahaka10    schedule 18.11.2015
comment
@thuga TheDarkKnight понимает правильно, но вы не ошибаетесь, мне также нужно будет выполнить это для изображений гораздо большего размера (4096x8192 или, может быть, даже 16384x16384).   -  person honiahaka10    schedule 18.11.2015
comment
Я предлагаю показать ваш код в виде mcve, что даст нам лучшее представление о том, что вы делаете и можете помогите нам помочь вам.   -  person TheDarkKnight    schedule 18.11.2015
comment
В то же время я могу только догадываться о проблеме, но я бы получил свой собственный класс от QGraphicsItem с QImage в качестве члена класса, а затем нарисовал бы это в функции рисования элемента с вызовом функции drawImage рисовальщика .   -  person TheDarkKnight    schedule 18.11.2015
comment
Какое профилирование вы сделали, прежде чем перейти к оптимизации?   -  person Vlad Feinstein    schedule 18.11.2015
comment
@TheDarkKnight Я не думаю, что mcve будет возможен, показывая те же результаты с меньшим количеством кода, но я попробую. (Если мне удастся создать mcve, я не смогу отправить сообщение до пятницы.)   -  person honiahaka10    schedule 18.11.2015
comment
@VladFeinstein Что вы подразумеваете под профилированием? Анализируете производительность моей программы? Я ничего подобного не делал (даже не знал бы, как это сделать). Я вижу, что есть проблемы с производительностью, просто взглянув на экран (также удаление функции setPixmap() устранит проблемы с производительностью).   -  person honiahaka10    schedule 18.11.2015


Ответы (1)


Вместо того, чтобы использовать QGraphicsPixmapItem и каждый раз устанавливать изображение, я предлагаю создать собственный класс, производный от QGraphicsItem, и обновить элемент QImage. Вот пример, который показывает плавный переход обновления изображения 1024 x 1024 (обратите внимание, что он использует C++ 11)

class MyImage : public QGraphicsItem
{
public:

    MyImage()
        :QGraphicsItem(NULL)
    {
        img = QImage(1024, 1024, QImage::Format_RGB32);
        static int red = 0;
        static int green = 0;
        static int blue = 0;
        img.fill(QColor(red++%255, green++%255, blue++%255));

        QTimer* pTimer = new QTimer;
        QObject::connect(pTimer, &QTimer::timeout, [=](){

            // C++ 11 connection to a lambda function, with Qt 5 connection syntax
            img.fill(QColor(red++%255, green++%255, blue++%255)); 
            update();
        });

        pTimer->start(1000 / 30); // 30 frames per second
    }

private:
    virtual QRectF boundingRect() const
    {
        return QRectF(0, 0, 1024, 1024);
    }

    QImage img;

    void paint(QPainter *painter, const QStyleOptionGraphicsItem *, QWidget *)
    {
        painter->drawImage(0, 0, img);
    }
};

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

person TheDarkKnight    schedule 18.11.2015
comment
Спасибо, я просто хотел попробовать это, но ваш оператор QObject::connect(), кажется, создает проблемы: нет доступа к защищенному члену QTimer::timeout и много синтаксических ошибок. Кроме того, ваш оператор подключения выглядит довольно странно для меня... Когда я пытаюсь сделать свой собственный оператор подключения, он тоже не работает QObject::connect(pTimer, SIGNAL(timeout()), this, SLOT(updateImage())); - person honiahaka10; 18.11.2015
comment
Соединение - это синтаксис Qt 5 с C++11, который позволяет подключиться к лямбда-функции. Даже если вы не используете C++11, вам действительно следует принять синтаксис соединения Qt 5, поскольку он обеспечивает проверки во время компиляции, недоступные при использовании старых макросов SIGNAL и SLOT. - person TheDarkKnight; 18.11.2015
comment
Если ваше соединение updateImage() не работает, вам необходимо объявить его как слот и наследовать от QGraphicsObject вместо QGraphicsItem. QGraphicsObject дает сигнал элементам и функциональные возможности слотов. Используя C++ 11 и соединение Qt 5, вы можете подключиться к любой функции, даже если она не объявлена ​​как слот, поэтому она работает в приведенном выше примере. - person TheDarkKnight; 18.11.2015
comment
Спасибо QGraphicsObject работает! Я использую Qt4.8, так что это была проблема. Я сейчас попробую внедрить ваш пример в свой код и посмотреть, решит ли он мою проблему. - person honiahaka10; 19.11.2015
comment
Отлично, дайте нам знать, как у вас дела; О) - person TheDarkKnight; 19.11.2015
comment
Кажется, работает, спасибо! Это будет работать даже с pTimer->start(1000 / (4096/2.5)); ;) Но также я понял, что emit signal(this, "some other variables") также был связан с этой проблемой не только setPixmap() Использование emit signal("some other variables") без this при частоте обновления 4096/2,5 с работает нормально. Я не думаю, что мне больше понадобится этот сигнал в будущем, но я все же хотел бы знать, почему this вызывает эту проблему? - person honiahaka10; 20.11.2015