data it is called multiple times on the same cell, but for a <br>different role (eg : it is called once to get the text to display,<br>and another time to get the font size).<br><br>but you must make sure the data method returns very fast,<br>
because it will get called a lot, since the view itself contains<br>no data, so each time a repaint of a cell is needed, the data<br>method will get called.<br><br><div class="gmail_quote"><blockquote class="gmail_quote" style="border-left: 1px solid rgb(204, 204, 204); margin: 0pt 0pt 0pt 0.8ex; padding-left: 1ex;">
<br>
Message: 2<br>
Date: Thu, 14 May 2009 21:21:30 +0200<br>
From: TP <<a href="mailto:paratribulations@free.fr">paratribulations@free.fr</a>><br>
Subject: [PyQt] model/view/delegate: data() method called too many<br>
times? Performance problem<br>
To: <a href="mailto:pyqt@riverbankcomputing.com">pyqt@riverbankcomputing.com</a><br>
Message-ID: <<a href="mailto:qi7ud6-rgq.ln1@rama.fbx.proxad.net">qi7ud6-rgq.ln1@rama.fbx.proxad.net</a>><br>
Content-Type: text/plain; charset=us-ascii<br>
<br>
Hi everybody,<br>
<br>
I use model/view/delegate architecture of Qt.<br>
I have a problem of slowness in a small example given below. Run the script<br>
from a terminal to see all standard output.<br>
Try to play with the tree: expand items, click on cells, etc. You will find<br>
that the function "data" is called all the time by Qt. Too many times, I<br>
think. For example, we get on standard output sequences as:<br>
<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
data, col=1, row=2<br>
<br>
which means that the data function is called several times for the same<br>
cell! Why? It slows down a lot my "real world" application, which is much<br>
more complicated than this simple script.<br>
<br>
How to modify this "greedy" behavior of Qt?<br>
<br>
Thanks a lot<br>
<br>
Julien<br>
<br>
<br>
######################################"<br>
#!/usr/bin/env python<br>
# -*- coding: utf-8 -*-<br>
<br>
from PyQt4.QtCore import *<br>
from PyQt4.QtGui import *<br>
import sys<br>
<br>
<br>
class CustomProxyModel( QSortFilterProxyModel ):<br>
<br>
def filterAcceptsRow( self<br>
, source_row<br>
, source_parent_index ):<br>
<br>
return True<br>
<br>
<br>
class TreeROModel( QAbstractItemModel ):<br>
<br>
<br>
def __init__( self<br>
, parent = None ):<br>
<br>
super( TreeROModel, self ).__init__( parent )<br>
self.root = "toto"<br>
self.children = [<br>
"coco"<br>
, "line 1" ]<br>
self.children_offirstline = [<br>
"coucou" ]<br>
self.columncount = 2<br>
<br>
<br>
<br>
def rowCount( self, parent ):<br>
<br>
node = self.nodeFromIndex( parent )<br>
if node == self.root:<br>
return len( self.children )<br>
elif node == "coco":<br>
return 1<br>
else:<br>
return 0<br>
<br>
<br>
def columnCount( self, QModelIndex = None ):<br>
<br>
return 2<br>
return self.columncount<br>
<br>
<br>
def data( self, index, role ):<br>
<br>
content = None<br>
col = index.column()<br>
row = index.row()<br>
print "data, col=%i, row=%i" % (col, row)<br>
if role == Qt.DisplayRole:<br>
if col == 0:<br>
content = self.nodeFromIndex( index )<br>
elif row == 0:<br>
content = len( self.children ) - 1<br>
<br>
else:<br>
content = "nothing in this item"<br>
<br>
elif role == Qt.TextAlignmentRole:<br>
<br>
if col == 0:<br>
content = int( Qt.AlignTop|Qt.AlignLeft )<br>
else:<br>
content = int( Qt.AlignTop|Qt.AlignRight )<br>
<br>
if content != None:<br>
return QVariant( content )<br>
else:<br>
# default choice<br>
return QVariant()<br>
<br>
<br>
<br>
<br>
def index( self, row, column, parent_index ):<br>
<br>
parent = self.nodeFromIndex( parent_index )<br>
if parent == "coco":<br>
child = self.children_offirstline[0]<br>
else:<br>
child = self.children[ row ]<br>
index = self.createIndex( row<br>
, column<br>
, child )<br>
<br>
return index<br>
<br>
<br>
<br>
def nodeFromIndex( self, index ):<br>
<br>
if index.isValid():<br>
node = index.internalPointer()<br>
return node<br>
else:<br>
node = self.root<br>
return node<br>
<br>
<br>
def parent( self, child_index ):<br>
<br>
node = self.nodeFromIndex( child_index )<br>
if node == "coucou":<br>
index = self.createIndex( 0, 0, self.root )<br>
return index<br>
else:<br>
return QModelIndex()<br>
<br>
<br>
def allIndex( self ):<br>
<br>
yield QModelIndex()<br>
index = self.createIndex( 0, 0, self.children[0] )<br>
yield index<br>
index = self.createIndex( 0, 0, self.children_offirstline[0] )<br>
yield index<br>
<br>
<br>
<br>
class TreeROWidget( QWidget ):<br>
<br>
<br>
<br>
def __init__( self<br>
, TreeROModel_<br>
, title = None<br>
, parent = None ):<br>
<br>
super( TreeROWidget, self ).__init__( parent )<br>
<br>
# central tree view<br>
self.view = QTreeView( parent )<br>
self.view.setSelectionBehavior( QTreeView.SelectItems )<br>
<br>
# central tree model<br>
self.model = TreeROModel_<br>
self.proxyModel = CustomProxyModel()<br>
self.proxyModel.setSourceModel( self.model )<br>
<br>
self.view.setModel( self.proxyModel )<br>
self.view.setAlternatingRowColors( True )<br>
<br>
<br>
self.connect( self.view, SIGNAL( "clicked(QModelIndex)" )<br>
, self.cellClicked )<br>
<br>
# layout<br>
vboxlayout = QVBoxLayout()<br>
hboxlayout = QHBoxLayout()<br>
vboxlayout.addLayout( hboxlayout )<br>
vboxlayout.addWidget( self.view )<br>
self.setLayout( vboxlayout )<br>
<br>
self.show()<br>
<br>
<br>
def cellClicked( self, qmodelindex ):<br>
<br>
if qmodelindex.isValid():<br>
qmodelindex = self.proxyModel.mapToSource( qmodelindex )<br>
print qmodelindex.internalPointer()<br>
<br>
<br>
<br>
class TreeWidget( TreeROWidget ):<br>
<br>
def __init__( self<br>
, TreeROModel_<br>
, title = None<br>
, parent = None ):<br>
<br>
super( TreeWidget, self ).__init__( parent = parent<br>
, TreeROModel_ = TreeROModel_<br>
, title = title )<br>
<br>
<br>
<br>
if __name__ == "__main__":<br>
<br>
def add_col():<br>
<br>
for index in widget.model.allIndex():<br>
print index, index.internalPointer()<br>
widget.model.beginInsertColumns( index, 2, 2 )<br>
widget.model.endInsertColumns()<br>
<br>
def add_row():<br>
<br>
index = QModelIndex()<br>
l = len( widget.model.children )<br>
widget.model.beginInsertRows( index, l, l )<br>
widget.model.children.append( "toto %i" % l )<br>
print widget.model.children<br>
widget.model.endInsertRows()<br>
<br>
app = QApplication( sys.argv )<br>
dialog = QDialog( )<br>
dialog.resize( 750, 550 )<br>
<br>
widget = TreeWidget( TreeROModel() )<br>
<br>
vboxlayout = QVBoxLayout( dialog )<br>
vboxlayout.addWidget( widget )<br>
dialog.setLayout( vboxlayout )<br>
dialog.show()<br>
widget.view.resizeColumnToContents( 0 )<br>
widget.view.resizeColumnToContents( 1 )<br>
<br>
pushbutton1 = QPushButton( "Add column in line 1" )<br>
pushbutton2 = QPushButton( "Add row" )<br>
vboxlayout.addWidget( pushbutton1 )<br>
vboxlayout.addWidget( pushbutton2 )<br>
<br>
QObject.connect( pushbutton1, SIGNAL( "clicked()" )<br>
, add_col )<br>
QObject.connect( pushbutton2, SIGNAL( "clicked()" )<br>
, add_row )<br>
<br>
app.exec_()<br>
<br>
<br>
<br>
--<br>
python -c "print ''.join([chr(154 - ord(c)) for c in '*9(9&(18%.\<br>
9&1+,\'Z4(55l4('])"<br>
<br>
"When a distinguished but elderly scientist states that something is<br>
possible, he is almost certainly right. When he states that something is<br>
impossible, he is very probably wrong." (first law of AC Clarke)<br>
<br>
<br>
<br>
</blockquote></div><br>