Important: Please read the Qt Code of Conduct -

QStandardItemModel/QtreeView fast setting background of items

  • I have a QTreeView, and I set it model...
    i need sometimes set background to one row of model,:
    @for(int i=0; i<myModel->columnCount(myIndex.parent()); ++i){
    myModel->setData( myModel->index(myIndex.row(), i, myIndex.parent()),QBrush(itemBackgroundCollor), Qt::BackgroundRole);
    but when I have a lot of rows in my model, it is very slow, it takes sometimes about three seconds

    is there any other faster way to do it?

  • It's because every single background change triggers a dataChanged signal and this in turn triggers some updates/repaints/reordering etc. in the view.
    Generally I'd recommend using a proper QAbstractItemModel which can provide the correct color directly via the reimplemented data function. If the backgrounds of many items then change, all you need to do is emit the dataChanged signal with the respective span of items once. But for a little improvement of performance, you could try disabling repaints during that for-loop, by placing yourView->setUpdatesEnabled(false) in front of it and reenabling updates afterwards.

  • I setUpdatesEnabled, but it doesnt seem to have any effect

  • I solve it by adding:

    but, couldnt it cause problems?

  • [quote author="Beka" date="1345101795"]but, couldnt it cause problems?[/quote]

    Yes, it's quite dangerous. At least call reset() on the views attached to the model after reenabling the signals. (Would be better to make the model emit modelReset(), but I don't think you can trigger that externally. The cleaner method would still be to make an appropriate QAbstractItemModel or QStandardItemModel subclass.)

  • i know, it would be better, but the signal of changed data is called from method QStandardItem::setData() and i dont want to subclass QStandardItem, because ones i try, and I finally didnt do it, because my model soemtimes use it, and sometiems not... but thats other issue...

    and reset on view, reseted it... there is nothing left

  • Hmm, why don't you use the models functions for it?
    QVariant Mymodel::data ( QModelIndex & index, role = Qt::DisplayRole )
    if (role == BackgroundRole)
    // check your index here and if the background should be changed?
    return QVariant;

  • but i need set the background, i know i want to change it, for all columns of one line, but i dont want to every time emit ignal itemChanged() ...
    function data only returns data, not change it

  • But if the function returns data to the model (which is a good way to keep the data shown in 1 place), you are able to use the signal:
    @void QAbstractItemModel::dataChanged ( const QModelIndex & topLeft, const QModelIndex & bottomRight ); @
    In here you are able to set the index to the row you want updated. Then use the code above (MyModel::data) to set the new data and background.
    If I'm missing the entire picture here, I'm sorry! Maybe post a picture of something to show what you want to achieve?

  • Okay, i have a tree of things, and in each column i have some data about the certain thing, and sometimes, when user click on special button, it is supposed to change color of current line, it is something which indicate what state have that thing...

    but I dont understand why I would change dataChanged signal, because i must set the color of each item in the line, i must setData, and there is only way to do it, by calling QStandardItem::setData, even the method QStandardItemModel::setData calls this function, and this function emit signal itemChanged, so whats the point of overriding other methods, when this finally will emit the signal??

Log in to reply