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:
panelUpdateTimer->setInterval(30);
connect(panelUpdateTimer, SIGNAL(timeout()), centralWidget, SLOT(repaint()));
panelUpdateTimer = new QTimer
panelUpdateTimer->setInterval(30);
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:
PANEL_ELEMENT_LIST::const_iterator itr;
for (itr = panelElements.begin(); itr != panelElements.end(); ++itr) {
(*itr)->update();
}
PANEL_ELEMENT_LIST::const_iterator itr;
for (itr = panelElements.begin(); itr != panelElements.end(); ++itr) {
(*itr)->update();
}
To copy to clipboard, switch view to plain text mode
Pretty simple.
The Instrument.paintEvent() method:
if (graphicPanel != NULL) {
graphicPanel->update();
}
if (graphicPanel != NULL) {
graphicPanel->update();
}
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?
Bookmarks