2

I have two questions.

  1. What is the difference between paint() of QGraphicsItem and paintEvent() of QWidget APIs?

  2. I am developing a timer kinda GUI, so I am updating the screen every 100ms with paint() API on embedded linux board. It consumes almost all of the CPU. Any idea how to prevent this?

Or is there any other method to do this simple graphics?

  1. Also I have multiple QGraphicsScene each with its own QGraphicsView in a grid layout. How to update the individual view from the MainWindow.

Below is the code how I currently do this:

/****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*****/
......

Hardware: TI-AM3354

jxgn
  • 741
  • 2
  • 15
  • 36
  • 1
    Also add the code that updates the items every 100ms. Having a timer per item is certainly not efficient, and it looks like you repaint everything even if nothing changed. Try to simply update the items if their properties change, and don't call update() manually at all. – Frank Osterfeld May 25 '15 at 08:09
  • I do update the scene every 100ms. I draw an arc with different start position, thereby making it as if it is rotating. And I also update time using drawText() inside the scene. Is there any other way without using QTimer on every scene? – jxgn May 25 '15 at 09:32
  • I just used one timer and the CPU was consumed fully by that one timer alone. – jxgn May 25 '15 at 09:33
  • How many scenes do you have? – thuga May 25 '15 at 09:51
  • I got 10 scenes to update. Just testing with one for now. – jxgn May 25 '15 at 09:54
  • In the case of rotation, try to rotate the item using http://doc.qt.io/qt-5/qgraphicsitem.html#setRotation instead of repainting it every frame. Using OpenGL might also help. – Frank Osterfeld May 25 '15 at 10:52
  • OpenGL would be an overhead for this. Anyways, now I need to update it only every minute so it won't be an issue. And I have a memory related question. In the above code, I create scenes and `MyItem` objects using `new`, so is it ok to leave those without deleting? Since this is the only application running in the system...Thanks for your time :) – jxgn May 26 '15 at 13:22

1 Answers1

2
  1. paintEvent() is a generic event handler and is called by Qt to paint a widget, usually the whole widget, but that sometimes can be optimized by respecting QPaintEvent's region and rect properties.
  2. paint() is called on individual QGraphicsItems by a QGraphicsView when painting the QGraphicsScene. It usually won't be called on all items, QGraphicsView does various checks before painting the item, e.g. ensuring that the item is in the viewport and not hidden by other items, etc.

From the code you posted, I see two optimizations: First, don't run a QTimer individually for each item, but one timer for the whole scene. Right now your code triggers up to N repaints every 100 ms, instead of a single one. Also, update the properties of your items and let them call QGraphicsItem::update() on themselves if the property actually changed, instead of updating the whole scene unconditionally.

Frank Osterfeld
  • 24,815
  • 5
  • 58
  • 70
  • Call QGraphicsItem::update() http://doc.qt.io/qt-5/qgraphicsitem.html#update when the item actually changed and only then – Frank Osterfeld May 25 '15 at 10:48
  • I change the visuals of the item i.e call `update()` on the slot of `QTimer` every 1 minute now. And for the single timer idea, should I register an event for each item and use it in timerEvent()? Thanks again for your help :) – jxgn May 26 '15 at 13:34
  • I am updating each view in a separate slot like this `connect(item_1->timer, SIGNAL(timeout()),this, SLOT(updateUI_1()));` and inside `updateUI_1()` I call `scene_1->update()` Can you please let me know is this the correct way? – jxgn May 27 '15 at 11:13
  • You shouldn't have to call update() on the scene at all, just update the item properties and let them call update() internally if the property actually changed – Frank Osterfeld May 27 '15 at 17:59