Solved Delegate in QTableView loads CPU & Performance impact
-
Hello,
Here is the scenario -
I have QTableView, with a default look and feel. In the runtime, I keep adding rows based on the incoming data. This is case, even after adding up 20,000 rows, My application looks smooth and cool. I don't see CPU load getting affected and I don't see any lag in performance.
My requirement is similar but the QTableView, look and feel changes. I use delegates and customize the table view. And in the run time I keep adding the rows based on the incoming data. In this case, just after adding up 1000 rows, I see the performance getting impacted, the slow responsiveness and also CPU hitting high.
This happens on ARM based embedded target board.
I understand that, when I use delegate to have custom widget, I create new objects. Each row would have say 4-5 widgets like label, pushbutton, etc.
Is that causing the performance as I am using a lot memory?What could be the problem and what is the best way to handle this situation
I can imagine there would be applications with millions of data, using custom delegates, still there would be a fluid response. How do I achieve that?
Thanks,
Kumara -
Hi,
How are you implementing your delegate ? Are you instantiating widgets in the paint function ?
-
@SGaist said:
How are you implementing your delegate ? Are you instantiating widgets in the paint function ?
Hi Sam,
I am implementing delegate and not using paint event.
Here is the code snippet.
TableView -
QueueOperationsDelegate* delegate = new QueueOperationsDelegate( this ); m_tableView->setItemDelegateForColumn( 0 , delegate );
And I have implemented create editor in delegate
QWidget *QueueOperationsDelegate::createEditor( QWidget *parent , const QStyleOptionViewItem &option , const QModelIndex &index ) const { Q_UNUSED( option ) QAbstractTableModel* model = ( QAbstractTableModel* )( index.model() ); QVariant varVal = model->data( index ); QUEUE_DATA* queueData = varVal.value < QUEUE_DATA* >(); QueueOperationCustomWidget *qOpCustomWidget = new QueueOperationCustomWidget( parent ); qOpCustomWidget->setRowItemValue( queueData , index.row() + 1); return qOpCustomWidget; }
So in a column 0, I am creating my own widget.
One problem what I noted just now is that, every time I add a row I have to edit all the rows in open persistent editor. I dont know why I have to do that for all the rows. It makes sense to do that for the row that is added newly.
If I dont call this function for all the rows, then I see only the newly added row reflects the custom widgetfor ( int var = 0; var < m_noOfRows; ++var ) { m_tableView->openPersistentEditor( m_queueModel->index( var , 0 , QModelIndex() ) ); }
And the paint function looks like this -
void QueueOperationsDelegate::paint( QPainter *painter, const QStyleOptionViewItem &option, const QModelIndex &index ) const { Q_UNUSED( painter ) Q_UNUSED( option ) Q_UNUSED( index ) }
I would be very much interested to understand the basics around persistent editor.
Thanks,
Kumara -
One thing that you should change is the part where you query the model in createEditor, there's the setEditor data function that is dedicated for that.
Now about your problem, if I understand you correctly, you are currently trying to create 20'000 widgets since you set a permanent editor on each entry.
Why do you need that ?
If you really need this then I'd recommend using a smarter logic where you only create/show the delegates for the visible items and destroy them otherwise. This will keep the widget count low and improve performances.
-
@SGaist Makes sense! I will make the changes, test it and post the results soon.
Thanks,
Kumara -
@SGaist This was good!
I have implemented to have the objects only for visible items and destroy them when they go out of visibility. This has improved the memory usage and also the performance.
Thanks!
-
@kumararajas , how did you make the widget only be created for the visible cells? I can't write it in the model. But I did not find information about visible cells in QTableView.