I've seem some other posts describing problems with performance with QAbstractItemModel, but nothing that quite matches my issue. I was using a table model, but have decided that I need some rows to expand to display supplemental information for the row, and the tree model/view seems to be ideal for that. The tricky thing is that one column of data may need to flash every half-second.
When I was using the table model, I implemented a slot, connected it to a timer, scan through the data rows to determine which ones need to flash, and then emit dataChanged for the cell where flashing is needed. I also flip a bool value in there. In the "data" method, I check the flag and switch the drawing colors for the foreground and background roles. This works fine with good performance, even with my data model of 2000 rows and every item in that one column flashing for all rows. CPU is at about 8%, and flashing clearly occurs on time.
When I switched to QAbstractItemModel and QTreeView, I had to implement "index" and "parent" as well, plus make a few other minor adjustments, and the performance is abysmal. CPU is at 100%, and it's only able to flash about every three seconds. Since I haven't added any of the supplmental data, the model is essentially identical, so I was a bit shocked at the perfomance difference.
The flashing is clearly the issue because if I disable it, everything is good. One improvement I've already tried is to emit dataChanged fewer times; for simplicity, I originally emitted it once for each cell (so it was emitted 2000 times every half-second), but when I hit this problem, I changed it to emit for contiguous cells. (All cells in the column currently flash, so now it's emited once every half-second.) That didn't make any difference at all, at least not noticeably (and suprisingly).
I couldn't think of any way to implement flashing other than emitting dataChanged for the cells that need to redraw every half-second. I'm a little frustrated with the fact that the model is responsible for visualization items (fonts, colors, and so on), rather than the view. In this case, I have to emit dataChanged for many, many rows that aren't on view.
I've considered pretending that the flashable column is doubled, and alternating between which one is shown in the model. It's a weird idea, and I haven't yet tried it because it seems like it might introduce more problems than it solves, but I'm at a bit of a loss here.
I see that there's a dataChanged slot in the view, and if I knew which rows were visible in the view, I could call that slot, but the view doesn't seem to provide me with an easy way to get the top-left and bottom-right model indexes of what's currently visible.
Ideas?
Thanks,
Doug
Added after 19 minutes:
I found that "setUniformRowHeights (true)" on the QTreeView solved the performance problem, and since my row heights are indeed uniform, that's a workable solution. Apparently, recalculating independent sizes for each changed cell was the issue.
However, I'm still interested in hearing about better ways to implement flashing in a tree or table view. I suspect delegates might be involved, but I haven't figured them out yet. The whole model/view documentation, including the two books I have, is pretty inadequate, at least the instant you jump off into the slightest of unusual territories. There's just not enough detail.
Thanks,
Doug
Bookmarks