QAbstractItemView::openPersistentEditor causes a performance deterioration
-
I'm implementing a desktop application. Some of the widgets use a
QTableView
connected to a specialized model.I want to present some of the columns using a widget. So I subclassed
QStyledItemDelegate
and implemented this new widget. I want to show it all the time, not just when it's being edited, so I calledopenPersistentEditor
for each row and column I needed.But this is causing a performance deterioration of about 20%. If I removes the lines that call
openPersistentEditor
, the performance deteriorarion is solved, so I assume this is causing the problem.
Any ideas? One solution might be to overrideQStyledItemDelegate::paint
, but it doesn't seem to be necessary considering that you can useopenPersistentEditor
. May I be doing something wrong?Some of the code:
QWidget *ComboBoxDelegate::createEditor(QWidget *parent, const QStyleOptionViewItem &option, const QModelIndex &index) const { QComboBox *view_selector = new QComboBox(parent); view_selector->setEditable(false); view_selector->setInsertPolicy(QComboBox::NoInsert); QStringList items = QStringList() << "item_1" << "item_2" << "item_3"; view_selector->addItems(items); QModelIndex type_index = index.siblingAtColumn(ChannelsTableModel::COLUMN_TYPE); connect(view_selector, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &ComboBoxDelegate::commitEditor); return view_selector; } void ComboBoxDelegate::setEditorData(QWidget *editor, const QModelIndex &index) const { QComboBox *view_selector = static_cast<QComboBox *>(editor); int index_value = index.data(Qt::DisplayRole).toInt(); if (index_value >= 0 && index_value < view_selector->count()) { view_selector->setCurrentIndex(index_value); } } void ComboBoxDelegate::setModelData(QWidget *editor, QAbstractItemModel *model, const QModelIndex &index) const { QComboBox *view_selector = static_cast<QComboBox *>(editor); int index_value = view_selector->currentIndex(); model->setData(index, index_value, Qt::DisplayRole); } void ComboBoxDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const { editor->setGeometry(option.rect); }
And I'm calling
openPersistentEditor
in this way (column
was previously defined):for (int i = 0; i < _table_model->rowCount(); ++i) { _table->openPersistentEditor(_proxy_model->index(i, column)); }
-
@Fran-Sansone said in QAbstractItemView::openPersistentEditor causes a performance deterioration:
I want to present some of the columns using a widget. So I subclassed QStyledItemDelegate and implemented this new widget. I want to show it all the time, not just when it's being edited, so I called openPersistentEditor for each row and column I needed.
Well I'm sure "editing" has an overhead. Why do this, you should be able use a `QStyledItemDelegate" for items from a view for display as well as editing? ("One solution might be to override QStyledItemDelegate::paint, but it doesn't seem to be necessary" yes you should try this instead of putting into edit mode.)
Having said that, if you have lots of these widgets there may be some hit. Many places only display an editing widget when actually editing. If he sees this @VRonin is your man in this area :)
-
Persistent editors are in the same category as index widgets (and under the hood it's the same) - try to avoid them and for sure don't add a lot of them. Use a custom QStyledItemDelegate instead.
-
If your custom widget is complex it might be worth using an intermediate solution like https://pastebin.com/XrppLZ3m
-
I am noticing a similar issue. I measure the cost of createEditor compared to the openPersistentEditor, and while it does take time, there seems to be a significant overhead in the openPersistentEditor outside of the createEditor itself. So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor, the rest is in the overhead of openPersistentEditor. I am digging to find some more, because it is much more expensive than expected.
Looking at the source code, there are 2 additional things that openPersistentEditor does besides createEditor. There is the visualRect() call and editor->show() call. There is also some overhead outside of openPersistenEditor like sizeHintForColumn() and sizeHintForRow(). I'm not sure what else yet.
Would be nice to get some hints from Qt on this issue.
-
@esmolikowski said in QAbstractItemView::openPersistentEditor causes a performance deterioration:
Would be nice to get some hints from Qt on this issue
What do you want to hear? We already told you that you should avoid them. What T
Qt version do you use? Please provide some code so we can reproduce it. -
@esmolikowski said in QAbstractItemView::openPersistentEditor causes a performance deterioration:
So say the sum of all the openPersistentEditor is 100ms only about 50ms of that is in the actual createEditor
I don't understand what the real-world issue is. Opening an editor is probably invoked by a user action (like clicking something), maybe you just invoke it from code without that I can't be sure. Then the user has to interact with it to perform some editing operation. Even if there is a delay of a tenth or a twentieth of a second does that really affect the user experience?
-
In order to have a pretty UI and make things more visible to our users, we openPersistentEditor for all QModelIndexes that have/need a custom widget. Say for example, I'd like to have a 'trash' button on each row to allow the user to delete a line item without going through a menu (think web style), we have a persistenEditor on each of those items.
-
@esmolikowski Hi,
Opening a persistent editor for a Trash button is typically a wrong use case. Create a custom QStyledItemDelegate to draw the button and handle the interaction.
-
That's exactly what I do. And for the editor to always visible, I use a persistent editor. I've got another case with a custom QLineEdit.