4

I have custom data that I need to display in a QTreeView. I have derived my model from QAbstractTableModel, and made my own implementations of rowCount(), columnCount(), data(), and headerData(). The model has a local QList> to support it, and the data() function is defined to read the values out of that list of lists directly corresponding to the row and column received in the QModelIndex parameter. There are two issues I'm running into.

The first is that the load of a very large file is quite slow, which is understandable. The second is that the scroll action is painfully slow, which I am not really understanding. Turns out that if I pull the scroll handle down, the GUI hangs for about 20 seconds, and then pops back. If I pull the handle a greater distance down, the hang time increases accordingly. If I pull the handle all the way to the bottom of the scroll bar, after waiting for the application to become responsive again, I can pull the handle up and down and get much better response.

It seems to me that QTreeView is only asking for a small chunk of the available data, but when I have pulled the scroll handle all the way to the bottom of the scroll bar, once the application becomes responsive again, it has by that point read all the data.

Is there a way to program for a much more responsive experience with scrolling for large data? I don't mind a longer wait up front, so just something like forcing the view to read all data from the model up front would work.

I have also thought that I could go back to just deriving from QAbstractItemView and controlling how it requests and stores data, only allowing for storing the viewed data, plus a buffer of entries before and after the viewed data. That of course would mean I'd have to control the scroll bar, since the handle sizing would indicate a small amount of data, and I would like it to look to the user as it should for the size of data they are dealing with. Not really wanting to go there if I don't have to.

Cœur
  • 37,241
  • 25
  • 195
  • 267
bmahf
  • 965
  • 2
  • 11
  • 27
  • How large is very large? Have you run your code through a profiler while interacting with the tree view? Why are you using a `QAbstractTableModel` with a `QTreeView`? – Jason R Apr 22 '15 at 16:33
  • 100,000 entries, each with 3 columns, one date, one code number, and one text string that can be anywhere from 30 to 200 characters each. I haven't tried a profiler yet. Thought I'd see if there was something simple I may be doing wrong, like using a QAbstractTableModel with a QTreeView. – bmahf Apr 22 '15 at 18:14
  • I was trying different configurations and the QAbstractTableModel with QTreeView ended up working. I have tried to change the QTreeView to a QTableView, but after I read in the data and send a dataUpdated() signal (my own definition connected to the QTableView::reset()), I am not getting into the data() method of the model. With a QTreeView, this wasn't a problem. – bmahf Apr 22 '15 at 18:20
  • It sounds like you could have a problem in your model implementation. I would recommend running Qt's [Model Test](http://wiki.qt.io/Model_Test), as it can help detect common errors. Writing a model subclass is quite error-prone in my experience. – Jason R Apr 22 '15 at 18:26
  • Tried setting up to use Model Test using the link you gave. For other people's information, there was a mistake modeltest.pri, but it turns out I needed to include modeltest.pro. Kept getting a build error message saying "Error: dependent 'tst_modeltest.cpp' does not exist.", even though the file is right in there with the other cpp and h files. I copied the whole modeltest folder into my project and tried it from in there. Same results. – bmahf Apr 22 '15 at 19:47
  • It's really strange that changing from QTreeView to QTableView causes the model's data() function not to be called. Both have a reset() slot that I am calling in either case. – bmahf Apr 22 '15 at 19:48
  • I put debug statements into rowCount(), columnCount(), and data(), and when I send the data updated signal. Both rowCount() and columnCount() are hit before I signal, but after my signal, none of the three are hit. – bmahf Apr 22 '15 at 19:54

2 Answers2

11

Two things:

  • Re-implement fetchMore() and canFetchMore() in your model. See this implementation example. Basically, the two functions allow lazy initialization of your data and should stop ui freezes.
  • Replace your usage of reset() and dataChanged() to use the insert and remove functionality. Right now, you are forcing the view to recalc which of 100,000 items to show.
p.i.g.
  • 2,815
  • 2
  • 24
  • 41
jonspaceharper
  • 4,207
  • 2
  • 22
  • 42
9

use

treeview view;
view.setUniformRowHeights(true);

Then view do n't hangs.

NDestiny
  • 1,133
  • 1
  • 12
  • 28