[PyQt] model/view/delegate: data() method called too many times?
Performance problem
TP
paratribulations at free.fr
Thu May 14 20:21:30 BST 2009
Hi everybody,
I use model/view/delegate architecture of Qt.
I have a problem of slowness in a small example given below. Run the script
from a terminal to see all standard output.
Try to play with the tree: expand items, click on cells, etc. You will find
that the function "data" is called all the time by Qt. Too many times, I
think. For example, we get on standard output sequences as:
data, col=1, row=2
data, col=1, row=2
data, col=1, row=2
data, col=1, row=2
data, col=1, row=2
data, col=1, row=2
data, col=1, row=2
which means that the data function is called several times for the same
cell! Why? It slows down a lot my "real world" application, which is much
more complicated than this simple script.
How to modify this "greedy" behavior of Qt?
Thanks a lot
Julien
######################################"
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from PyQt4.QtCore import *
from PyQt4.QtGui import *
import sys
class CustomProxyModel( QSortFilterProxyModel ):
def filterAcceptsRow( self
, source_row
, source_parent_index ):
return True
class TreeROModel( QAbstractItemModel ):
def __init__( self
, parent = None ):
super( TreeROModel, self ).__init__( parent )
self.root = "toto"
self.children = [
"coco"
, "line 1" ]
self.children_offirstline = [
"coucou" ]
self.columncount = 2
def rowCount( self, parent ):
node = self.nodeFromIndex( parent )
if node == self.root:
return len( self.children )
elif node == "coco":
return 1
else:
return 0
def columnCount( self, QModelIndex = None ):
return 2
return self.columncount
def data( self, index, role ):
content = None
col = index.column()
row = index.row()
print "data, col=%i, row=%i" % (col, row)
if role == Qt.DisplayRole:
if col == 0:
content = self.nodeFromIndex( index )
elif row == 0:
content = len( self.children ) - 1
else:
content = "nothing in this item"
elif role == Qt.TextAlignmentRole:
if col == 0:
content = int( Qt.AlignTop|Qt.AlignLeft )
else:
content = int( Qt.AlignTop|Qt.AlignRight )
if content != None:
return QVariant( content )
else:
# default choice
return QVariant()
def index( self, row, column, parent_index ):
parent = self.nodeFromIndex( parent_index )
if parent == "coco":
child = self.children_offirstline[0]
else:
child = self.children[ row ]
index = self.createIndex( row
, column
, child )
return index
def nodeFromIndex( self, index ):
if index.isValid():
node = index.internalPointer()
return node
else:
node = self.root
return node
def parent( self, child_index ):
node = self.nodeFromIndex( child_index )
if node == "coucou":
index = self.createIndex( 0, 0, self.root )
return index
else:
return QModelIndex()
def allIndex( self ):
yield QModelIndex()
index = self.createIndex( 0, 0, self.children[0] )
yield index
index = self.createIndex( 0, 0, self.children_offirstline[0] )
yield index
class TreeROWidget( QWidget ):
def __init__( self
, TreeROModel_
, title = None
, parent = None ):
super( TreeROWidget, self ).__init__( parent )
# central tree view
self.view = QTreeView( parent )
self.view.setSelectionBehavior( QTreeView.SelectItems )
# central tree model
self.model = TreeROModel_
self.proxyModel = CustomProxyModel()
self.proxyModel.setSourceModel( self.model )
self.view.setModel( self.proxyModel )
self.view.setAlternatingRowColors( True )
self.connect( self.view, SIGNAL( "clicked(QModelIndex)" )
, self.cellClicked )
# layout
vboxlayout = QVBoxLayout()
hboxlayout = QHBoxLayout()
vboxlayout.addLayout( hboxlayout )
vboxlayout.addWidget( self.view )
self.setLayout( vboxlayout )
self.show()
def cellClicked( self, qmodelindex ):
if qmodelindex.isValid():
qmodelindex = self.proxyModel.mapToSource( qmodelindex )
print qmodelindex.internalPointer()
class TreeWidget( TreeROWidget ):
def __init__( self
, TreeROModel_
, title = None
, parent = None ):
super( TreeWidget, self ).__init__( parent = parent
, TreeROModel_ = TreeROModel_
, title = title )
if __name__ == "__main__":
def add_col():
for index in widget.model.allIndex():
print index, index.internalPointer()
widget.model.beginInsertColumns( index, 2, 2 )
widget.model.endInsertColumns()
def add_row():
index = QModelIndex()
l = len( widget.model.children )
widget.model.beginInsertRows( index, l, l )
widget.model.children.append( "toto %i" % l )
print widget.model.children
widget.model.endInsertRows()
app = QApplication( sys.argv )
dialog = QDialog( )
dialog.resize( 750, 550 )
widget = TreeWidget( TreeROModel() )
vboxlayout = QVBoxLayout( dialog )
vboxlayout.addWidget( widget )
dialog.setLayout( vboxlayout )
dialog.show()
widget.view.resizeColumnToContents( 0 )
widget.view.resizeColumnToContents( 1 )
pushbutton1 = QPushButton( "Add column in line 1" )
pushbutton2 = QPushButton( "Add row" )
vboxlayout.addWidget( pushbutton1 )
vboxlayout.addWidget( pushbutton2 )
QObject.connect( pushbutton1, SIGNAL( "clicked()" )
, add_col )
QObject.connect( pushbutton2, SIGNAL( "clicked()" )
, add_row )
app.exec_()
--
python -c "print ''.join([chr(154 - ord(c)) for c in '*9(9&(18%.\
9&1+,\'Z4(55l4('])"
"When a distinguished but elderly scientist states that something is
possible, he is almost certainly right. When he states that something is
impossible, he is very probably wrong." (first law of AC Clarke)
More information about the PyQt
mailing list