I'm trying to achieve a UI to monitor a list of connected sensors, something along the lines of this:



Most of the data in the table updates very slowly, if at all. The sensor number is static, the cell background image only updates when the selection changes, and the sensor name and status only changes occasionally (perhaps 1 time per hour).

The bar graph value, however, updates with incoming sensor data, which I receive every 50ms from each sensor. I currently wait for all sensors to report, update the whole model in one go, then emit a dataChanged() signal to update the table.

This still means I'm updating the table and drawing everything 20 times per second, which is really inefficient. Testing with 50 connected sensors results in a 30% CPU load. I may have systems in the future with hundreds of connections.

If I limit my delegate's paint routine to only drawing the sensor value bar graph, CPU time drops to less than 10%, including all my communication threads and other program duties.

How can I go about painting the bar graph without redrawing the whole table?

Methods I've tried (with the help of some people on stackoverflow):

Setting a 'graph only' flag before emitting dataChanged
This flag is checked by the paint routine, and if it's set, only the graph is drawn.

Doesn't work because: The paint routine clears the canvas before drawing, so whenever the flags are set only the graphs are drawn, not the cell background or pseudo-static text.

Setting a 'graph only' flag and using setAttribute(Qt::WA_OpaquePaintEvent)
Same as above, but setting this value in the table's constructor.

Doesn't work because: Graphs are drawn correctly, but it causes issues with the rendering of the individual cells (transparency ignored, which I need).

Stacked QTableViews: Placing 2 tableviews on top of eachother, with the upper one drawing only graphs and the bottom drawing everything else.

Doesn't work because: Mouse events are intercepted by top, mostly invisible tableview. Qt::WA_TransparentForMouseEvents makes no difference. Trigging an update of the top tableview appears to trigger a refresh of the static tableview, so you have to use two models, two tables, and two delegates.


The last resort is to scrap the Qt MVC and do it all myself from scratch using paint events or OpenGL. I'd rather use TableViews because of the convenience and reusability.

The moment the best option seems to be the double tableview method, but I still can't figure out how to pass mouse clicks down to the next layer in the z-order. By setting the NoFocus focus policy on the top tableview I've got keyboard events working, but mouse clicks are still not registered.


Any ideas?