Results 1 to 3 of 3

Thread: QTableView paints too much

  1. #1
    Join Date
    Jan 2006
    Location
    Edmonton, Canada
    Posts
    101
    Thanks
    13
    Thanked 6 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default QTableView paints too much

    I have a GUI with a series of textboxes and a QTableView. Whenever the user clicks on a row, the textboxes will display the values of each column in the row, allowing the user to edit the contents.

    When the user edits the contents of a textbox, I determine the index of the row being edited and refresh the row from my QAbstractTableModel:
    Qt Code:
    1. void TableModel::refreshRow( const QModelIndex aModelIndex )
    2. {
    3. QModelIndex rowFirstColumn = index( aModelIndex.row(), 0, QModelIndex() );
    4. QModelIndex rowLastColumn = index( aModelIndex.row(), ( columnCount() - 1 ), QModelIndex() );
    5. emit dataChanged( rowFirstColumn, rowLastColumn );
    6. }
    To copy to clipboard, switch view to plain text mode 
    Due to design decisions beyond my control and outside the scope of this issue, I cannot use the QAbstractTableModel's setData method when I'm setting data from the textboxes - that's why I've written my own refresh method.

    Anyway, the problem I'm having is that after the dataChanged signal is handled by the QTableView, the entire table is redrawn again and I can't figure out what is causing that to happen. The result is that when the user types a letter in the textbox, there is a noticable lag between the keypress and the character appearing in the textbox and on the QTableView.

    I was able to determine that the entire table was being redrawn by putting a breakpoint in my QAbstractTableModel's data method, and I can see the method being called for all the visible cell indexes in the table, at least once for each role. Here is the bottom part of the stack trace at that point:
    Qt Code:
    1. > nrcs.exe!avid::nrcs::ui::model::TableModel::data(const QModelIndex & index={...}, int role=0) Line 151 C++
    2. QtGuid4.dll!QSortFilterProxyModel::data(const QModelIndex & index={...}, int role=0) Line 652 + 0x1d C++
    3. QtCored4.dll!QModelIndex::data(int arole=0) Line 321 + 0x4b C++
    4. QtGuid4.dll!QItemDelegate::paint(QPainter * painter=0x0012cbd8, const QStyleOptionViewItem & option={...}, const QModelIndex & index={...}) Line 238 + 0x12 C++
    5. QtGuid4.dll!QTableView::paintEvent(QPaintEvent * event=0x0012d348) Line 448 C++
    6. QtGuid4.dll!QWidget::event(QEvent * event=0x0012d348) Line 5121 C++
    7. QtGuid4.dll!QFrame::event(QEvent * e=0x0012d348) Line 598 C++
    8. QtGuid4.dll!QAbstractScrollArea::viewportEvent(QEvent * e=0x0012d348) Line 476 + 0xc C++
    9. QtGuid4.dll!QAbstractItemView::viewportEvent(QEvent * event=0x0012d348) Line 969 C++
    10. QtGuid4.dll!QAbstractScrollAreaPrivate::viewportEvent(QEvent * e=0x0012d348) Line 91 + 0x26 C++
    11. QtGuid4.dll!QAbstractScrollAreaViewport::event(QEvent * e=0x0012d348) Line 103 + 0xf C++
    12. QtGuid4.dll!QApplicationPrivate::notify_helper(QObject * receiver=0x0ac1d0a0, QEvent * e=0x0012d348) Line 3173 + 0xf C++
    13. QtGuid4.dll!QApplication::notify(QObject * receiver=0x0ac1d0a0, QEvent * e=0x0012d348) Line 3134 + 0x10 C++
    14. QtCored4.dll!QCoreApplication::sendSpontaneousEvent(QObject * receiver=0x0ac1d0a0, QEvent * event=0x0012d348) Line 174 + 0x3e C++
    15. QtGuid4.dll!qt_sendSpontaneousEvent(QObject * receiver=0x0ac1d0a0, QEvent * event=0x0012d348) Line 1228 + 0xe C++
    16. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 840 + 0xd C++
    17. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=2, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    18. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    19. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=6, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    20. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    21. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=1, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    22. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    23. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    24. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    25. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=2, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    26. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    27. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    28. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    29. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=4, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    30. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    31. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    32. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=2, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 767 + 0x20 C++
    33. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=3, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 767 + 0x20 C++
    34. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    35. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=1, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    36. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    37. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=1, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    38. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    39. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=0, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    40. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 870 + 0x28 C++
    41. QtGuid4.dll!QWidgetBackingStore::paintSiblingsRecursive(QPaintDevice * pdev=0x03053a10, const QList<QObject *> & siblings={...}, int index=55, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=4) Line 777 C++
    42. QtGuid4.dll!QWidgetPrivate::drawWidget(QPaintDevice * pdev=0x03053a10, const QRegion & rgn={...}, const QPoint & offset={...}, int flags=5) Line 870 + 0x28 C++
    43. QtGuid4.dll!QWidgetBackingStore::cleanRegion(const QRegion & rgn={...}, QWidget * widget=0x09f06920, bool recursiveCopyToScreen=true) Line 697 C++
    44. QtGuid4.dll!qt_syncBackingStore(QRegion rgn={...}, QWidget * widget=0x09f06920, bool recursive=true) Line 220 C++
    45. QtGuid4.dll!QETWidget::translatePaintEvent(const tagMSG & msg={...}) Line 3445 + 0x2b C++
    46. QtGuid4.dll!QtWndProc(HWND__ * hwnd=0x00220a3c, unsigned int message=49687, unsigned int wParam=0, long lParam=0) Line 1439 + 0xc C++
    To copy to clipboard, switch view to plain text mode 

    Any ideas what is causing this to happen and what I can do to improve performance?

  2. #2
    Join Date
    Jan 2006
    Location
    Warsaw, Poland
    Posts
    33,359
    Thanks
    3
    Thanked 5,015 Times in 4,792 Posts
    Qt products
    Qt3 Qt4 Qt5 Qt/Embedded
    Platforms
    Unix/X11 Windows Android Maemo/MeeGo
    Wiki edits
    10

    Default Re: QTableView paints too much

    As far as I understand the code responsible for updating the view, it looks like the view only checks whether you update one cell or more. In the first case, it only updates that single item. Otherwise it just asks the viewport to update itself causing all visible data to be reread.

    Here is the code:
    Qt Code:
    1. void QAbstractItemView::dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight)
    2. {
    3. // Single item changed
    4. if (topLeft == bottomRight && topLeft.isValid()) {
    5. if (d->hasEditor(topLeft))
    6. itemDelegate()->setEditorData(d->editorForIndex(topLeft), topLeft);
    7. else if (isVisible() && !d->delayedLayout.isActive()) // otherwise the items will be update later anyway
    8. d->viewport->update(visualRect(topLeft));
    9. return;
    10. }
    11. updateEditorData(); // we are counting on having relatively few editors
    12. if (!isVisible() || d->delayedLayout.isActive())
    13. return; // no need to update
    14. d->viewport->update();
    15. }
    To copy to clipboard, switch view to plain text mode 

    You might want to subclass and reimplement this method to only update this part which did actually change (you need to change the last line of this method to take the appropriate rectange as a parameter).

  3. The following user says thank you to wysota for this useful post:

    Jimmy2775 (26th July 2006)

  4. #3
    Join Date
    Jan 2006
    Location
    Edmonton, Canada
    Posts
    101
    Thanks
    13
    Thanked 6 Times in 5 Posts
    Qt products
    Qt4
    Platforms
    MacOS X Unix/X11 Windows

    Default Re: QTableView paints too much

    That sounds like it would work, but when I tried to implement that function I got compiler errors starting at the statement Q_D(QAbstractItemView); - 'QTableView::d_func' : cannot access private member declared in class 'QTableView'. I have to apoligize here but I am new to both Qt and C++, so while I realize that this is related to the private d pointer, I don't fully understand what's happening here or how to make my derived class work. Is there anything written on the internet that can enlighten me on this subject?

    You pointed out that the view will update either individual cells, or the entire table, so for now I've created a loop and emit dataChanged signals for each cell in the row. This has improved performance dramatically, but I would eventually like to implement the solution you suggested wysota.

Similar Threads

  1. Set height of QTableView to fit exact number of rows.
    By Ben.Hines in forum Qt Programming
    Replies: 3
    Last Post: 17th January 2019, 02:49
  2. QTableView sorting
    By gabriels in forum Qt Programming
    Replies: 11
    Last Post: 6th October 2010, 18:13
  3. QTableView currentChanged <> selecting header
    By Everall in forum Qt Programming
    Replies: 4
    Last Post: 1st April 2009, 09:24
  4. Multi-line messages in QTableView
    By Conel in forum Qt Programming
    Replies: 6
    Last Post: 13th April 2006, 14:49
  5. Sorting QTableView
    By Jimmy2775 in forum Qt Programming
    Replies: 7
    Last Post: 9th February 2006, 17:47

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.