ListView is (very) slow to move to current item
-
Hi,
(I don't know why my previous post does not appears, sorry it appear twice).I'm using a listview to display a list of 600 element, it appear that when I select alternatively first and last element, the listview take a long (long) time to scroll (animation) from first to last element (around 5s on my 2.5Ghz windows vista, Core2duo CPU).
This slow speed seems to be linked to- the usage of a javascript array as model
- a 'complex' listview delegate to display element (not so complex in my point of view, but maybe a qml limitation ?)
Debugging by adding trace on listview's delegate text, I can see that listview visit/create all element between first and last when it scrolls. As my element have same height, is there a way to declare that to listview in order to accelerate it ?
Thanks for your help and suggestions,
Arnaud.PS: test source code (use a 6s timer to select first/last/first/last/... element of list view)
@import Qt 4.7
import "TestListViewSlow2.js" as JSRectangle {
id: id0
width : 400
height : 600ListView { id : idLV clip: true width : id0.width height : id0.height focus: true model: 0 // see onCompleted highlightFollowsCurrentItem: true highlightMoveDuration: 300 highlight: Rectangle { border.color : "black" radius: 4 width: idLV.width gradient : Gradient { GradientStop { position: 0.0; color: "lightsteelblue" } GradientStop { position: 0.5; color: "white" } GradientStop { position: 1.0; color: "lightsteelblue" } } } Component { id: itemDelegate Item { width: idLV.width; height: tx1.height+10 id : item Text { id: tx1; x:10; y: 6; text: idLV.model[index].name width : parent.width -10-10 -rect.width -(idIMG.visible ? (idIMG.width+3) : 0)-(idIMG2.visible ? (idIMG2.width+6) : 0) font.pixelSize:12; elide:Text.ElideMiddle
// onTextChanged: {
// console.log(" completed item index="+index)
// }
}
Rectangle { //tag element having is_also_authors flag
id:idIMG
visible: idLV.model[index].is_also_author ? idLV.model[index].is_also_author : false
color : "green"
x: tx1.x+tx1.width+3
width: 16 ; height: 16; radius: 8
anchors.verticalCenter : parent.verticalCenter
}
Rectangle { //tag elemnt having is_illustrator
id:idIMG2
visible: idLV.model[index].is_illustrator ? idLV.model[index].is_illustrator : false
//source: "images/camera.png"
color: "darkMagenta"
width: 16; height: 16; radius:8
x: idIMG.visible ? (idIMG.x+idIMG.width+3) : tx1.x+tx1.width+3
anchors.verticalCenter : parent.verticalCenter
}
Rectangle {
id: rect
color : idLV.model[index].valid ? "midnightBlue" : "darkRed"
radius: height/2
smooth:true
width : tx2.width+tx2.height+4
height: tx2.height+4
y : 5
x : item.width-8-width
Text { id: tx2; text: idLV.model[index].count; font.pixelSize : 10; color:"white"
anchors.verticalCenter:rect.verticalCenter; anchors.horizontalCenter: rect.horizontalCenter }
}
MouseArea {
anchors.fill : parent
onClicked: {
idLV.currentIndex = index
}
}
}
}
delegate: itemDelegateComponent.onCompleted: { idLV.model = JS.getModel() } } Timer { id: idTimer repeat: true interval: 6000 triggeredOnStart: true onTriggered: { //force full scroll of list view var nci = idLV.currentIndex==0 ? 580 : 0 console.log("Timer set idLV.currentIndex = "+nci) idLV.currentIndex = nci } running: true }
}
@The associated .js file:
@.pragma libraryvar model_cache
function getModel() {
if( !model_cache ) {
model_cache = __createModel()
}
return model_cache
}function __createModel() {
var ary = []
for( var i=0; i<600; i++ ) {
var e = { name: "Entry #"+i, count: 1, valid: true }
e.count = i
if( i==0 ) e.valid=false
if( i%8==0 ) {
e.is_illustrator = true
if( i==0 ) {
e.is_also_author = true
}
}
ary.push( e )
}return ary
}
@ -
-
Write my own listview it's possibility, but a total waste of time.
enhance behior/ability of existing listview may be more useful for more people. (I guess)In my point of view, if listview visits all element in order to get their height,
it must exist a property of listview saying 'all elements have same height'.
With that property listview may discover once the height and remember it in order to accelerate the scroll.(thanks for pointing me thread 1368, it's the same issue).
-
ListView will move the highlight from its current position to the new current item, scrolling the view as it moves. If your model is slow to provide data or you have a complex delegate then it will struggle to scroll smoothly. The best solution is to move the view directly to the target index and then set the currentIndex, e.g.
@
idLV.positionViewAtIndex(nci, ListView.Visible)
idLV.currentIndex = nci
@ -
[quote author="Alexander Kuchumov" date="1292868441"]Andre, where is it in QListView? QListView also evaluates height for all elements.[/quote]
It is right "here":http://doc.qt.nokia.com/4.6/qlistview.html#uniformItemSizes-prop. You can tell QListView that the items are all the same size, and then it only evaluates the hight of the first item. -
Hi, I have a problem similar to yours. I have a ListView with possibly thousands of elements. I keep a property in my PySide backend which is the currentIndex for my ListView. Whenever I change the index, the ListView should scroll to the current item.
It works, but the scrolling is very slow. I think it is the same problem you are describing. Do you have any idea how should I solve my case?