paint() против paintEvent() в Qt

У меня есть два вопроса.

  1. В чем разница между paint() из QGraphicsItem и paintEvent() из QWidget API?

  2. Я разрабатываю графический интерфейс таймера, поэтому я обновляю экран каждые 100 мс с помощью paint() API на встроенной плате Linux. Он потребляет почти весь процессор. Любая идея, как предотвратить это?

Или есть другой способ сделать эту простую графику?

  1. Также у меня есть несколько QGraphicsScene, каждый со своим QGraphicsView в сетке. Как обновить отдельный вид из MainWindow.

Ниже приведен код, как я сейчас это делаю:

/****SCENE 1*****/
    scene_1 = new QGraphicsScene();
    scene_1->setBackgroundBrush(Qt::black);
    ui->gv_1->setScene(scene_1);
    ui->gv_1->setRenderHint(QPainter::Antialiasing);
    circle = scene_1->addEllipse(50, 80, 150, 150, outlinePen, darkGreyBrush);
    textSlotNo = scene_1->addText("1", QFont("Arial", 30) );
    textSlotNo->setDefaultTextColor(Qt::gray);
    textSlotNo->setPos(0,50);

    MyItem *item_1 = new MyItem(1);
    scene_1->addItem(item_1);
    item_1->timer = new QTimer();
    connect(item_1->timer, SIGNAL(timeout()),scene_1, SLOT(update()));
    item_1->timer->start(100);

/****SCENE 2*****/
......

Оборудование: TI-AM3354


person Xavier Geoffrey    schedule 25.05.2015    source источник
comment
Также добавьте код, который обновляет элементы каждые 100 мс. Наличие таймера для каждого элемента, безусловно, неэффективно, и похоже, что вы перерисовываете все, даже если ничего не изменилось. Попробуйте просто обновить элементы, если их свойства изменились, и вообще не вызывайте update() вручную.   -  person Frank Osterfeld    schedule 25.05.2015
comment
Я обновляю сцену каждые 100 мс. Я рисую дугу с другим начальным положением, тем самым создавая впечатление, что она вращается. И я также обновляю время, используя drawText() внутри сцены. Есть ли другой способ без использования QTimer в каждой сцене?   -  person Xavier Geoffrey    schedule 25.05.2015
comment
Я только что использовал один таймер, и только этот таймер полностью потреблял ЦП.   -  person Xavier Geoffrey    schedule 25.05.2015
comment
Сколько у вас сцен?   -  person thuga    schedule 25.05.2015
comment
Мне нужно обновить 10 сцен. Пока тестирую с одним.   -  person Xavier Geoffrey    schedule 25.05.2015
comment
В случае ротации попробуйте повернуть элемент с помощью doc.qt.io/ qt-5/qgraphicsitem.html#setRotation вместо перерисовки в каждом кадре. Использование OpenGL также может помочь.   -  person Frank Osterfeld    schedule 25.05.2015
comment
OpenGL будет накладными расходами для этого. В любом случае, теперь мне нужно обновлять его каждую минуту, так что это не будет проблемой. И у меня вопрос по памяти. В приведенном выше коде я создаю сцены и MyItem объекты, используя new, поэтому можно ли оставить их, не удаляя? Так как это единственное приложение, работающее в системе... Спасибо за ваше время :)   -  person Xavier Geoffrey    schedule 26.05.2015


Ответы (1)


  1. paintEvent() является общим обработчиком событий и вызывается Qt для рисования виджета, обычно всего виджета, но иногда это можно оптимизировать, учитывая свойства области и прямоугольника QPaintEvent.
  2. paint() вызывается для отдельных объектов QGraphicsItem с помощью QGraphicsView при рисовании QGraphicsScene. Обычно он не вызывается для всех элементов, QGraphicsView выполняет различные проверки перед рисованием элемента, например. убедиться, что элемент находится в окне просмотра и не скрыт другими элементами и т. д.

Из кода, который вы разместили, я вижу две оптимизации: во-первых, не запускайте QTimer отдельно для каждого элемента, а один таймер для всей сцены. Прямо сейчас ваш код запускает до N перерисовок каждые 100 мс вместо одной. Кроме того, обновите свойства ваших элементов и позвольте им вызывать QGraphicsItem::update() на самих себя, если свойство действительно изменилось, вместо безусловного обновления всей сцены.

person Frank Osterfeld    schedule 25.05.2015
comment
Вызов QGraphicsItem::update() doc.qt.io/qt-5/qgraphicsitem .html#update, когда элемент фактически изменился, и только после этого - person Frank Osterfeld; 25.05.2015
comment
Я меняю визуальные эффекты предмета, т.е. вызываю update() в слоте QTimer теперь каждую минуту. И что касается идеи с одним таймером, должен ли я регистрировать событие для каждого элемента и использовать его в timerEvent()? В очередной раз благодарим за помощь :) - person Xavier Geoffrey; 26.05.2015
comment
Я обновляю каждое представление в отдельном слоте, например connect(item_1->timer, SIGNAL(timeout()),this, SLOT(updateUI_1()));, а внутри updateUI_1() я вызываю scene_1->update() Не могли бы вы сообщить мне, правильно ли это? - person Xavier Geoffrey; 27.05.2015
comment
Вам вообще не нужно вызывать update() на сцене, просто обновите свойства элемента и позвольте им вызывать update() внутренне, если свойство действительно изменилось. - person Frank Osterfeld; 27.05.2015