I have a real-time data collection/graphing application that is chewing up what seems like an inordinate amount of CPU time in the graphics infrastructure.

The application consists of an instrument panel (that extends QMainWindow). I use a QWidget as the central widget.

When the data collection starts I start a timer to update the display, as in:
Qt Code:
  1. panelUpdateTimer = new QTimer
  2. panelUpdateTimer->setInterval(30);
  3. connect(panelUpdateTimer, SIGNAL(timeout()), centralWidget, SLOT(repaint()));
To copy to clipboard, switch view to plain text mode 
30 ms refresh rate gives me 33.3 frames/sec. The QTimer overhead adds about 5% CPU load. not bad....

The central widget is populated with a collection of custom instruments, each of which extend QWidget. I use a QBoxLayout in the central widget to manage the instruments.

Each instrument also includes a collection of custom QWidgets (axis, title, legend, graphic, etc.). I also use QBoxLayout to manage the layout of those little widgets.

The centralWidget.paintEvent() method:
Qt Code:
  1. PANEL_ELEMENT_LIST::const_iterator itr;
  2. for (itr = panelElements.begin(); itr != panelElements.end(); ++itr) {
  3. (*itr)->update();
  4. }
To copy to clipboard, switch view to plain text mode 
Pretty simple.

The Instrument.paintEvent() method:
Qt Code:
  1. if (graphicPanel != NULL) {
  2. graphicPanel->update();
  3. }
To copy to clipboard, switch view to plain text mode 
Again, very simple. The graphicPanel.paintEvent() draws a QPainterPath (with about 20 lines in it) and a sequence of more lines (e.g., an oscilloscope). I cache the lines to paint in a QLines array and use QPainter::drawLines() to draw them. Pretty efficient.

Now, the problem....

Just starting the QTimer to call the centralWidget::update() (which calls the centralWidget.paintEvent() method) adds about 5% CPU for a 30 ms refresh interval. not bad.

If that centralWidget.paintEvent() method calls each of the Instrument::update() methods (which wind their way to the Instrument.paintEvent() method, that adds a negligible amount of CPU time (1 - 2 % for 3 instruments).

However, just having the Instrument.paintEvent() method call the graphic::update() method (of its child) without the graphic.paintEvent() method even do anything causes the CPU utilization to spike to about 50% !. Adding the actual drawing of the lines is negligible.

I understand that I'm posting an QWidget.update() whist inside a QWidget.paintEvent(), but 50% CPU utilization seems excessive. If I don't call the graphic::update() method, the CPU is about 15% utilization.

That doesn't seem scalable.

Ideas?