I use a Listbox to draw the items of an array to the screen. The array can have different subclasses of fruits. Each fruit will have her own drawing procedure. So i add the fruits to the Listbox:
[h]FruitsListbox.Init[/h]
[code]Dim count As Integer = Fruits.Ubound
For I As Integer = o To count
Me.AddRow
Me.CellTag(Me.LastIndex, 0) = i
Select Case Fruits(i)
Case IsA Apple
Me.RowTag(Me.LastIndex) = FruitsListbox.RowType.Apple
Case IsA Banana
Me.RowTag(Me.LastIndex) = FruitsListbox.RowType.Banana
End Select
Next[/code]
[h]FruitsListbox.CellBackgroundPaint[/h]
[code]’ Background color
g.ForeColor = &cFFFFCC00
g.FillRect(0, 0, g.Width, g.Height)
If row < Me.ListCount Then
Select Case Me.RowTag(row)
Case FruitsListbox.RowType.Apple
DrawApple(g, Apple(Me.Fruits(Me.CellTag(row, 0))), row)
Case FruitsListbox.RowType.Banana
DrawBanana(g, Banana(Me.Fruits(Me.CellTag(row, 0))), row)
End Select
End If
Return True[/code]
The Listbox performance is really bad. The CPU climbs up more and more, by resizing the Window or scrolling the Listbox. Also the resizing by double clicking the Window’s Titlebar isn’t smooth. Is there any way to get it more soft and with less CPU performance? This is just a test, but after the Listbox will have e.g. 5000 rows and much more. I tried this also with @jim mckay s DataView, but this is even more performance-intensive.
First off… .DO NOT redraw your fruit in the CellBackgroundPaint
Pre-process the graphics (after all the “Apple” is still going to look the same, right?) and use ROWPICTURE instead
The performance is “bad” because you was burning tons of CPU resources doing unnecessary things over and over
For I As Integer = o To count
Me.AddRow
Me.CellTag(Me.LastIndex, 0) = i
Select Case Fruits(i)
Case IsA Apple
Me.RowTag(Me.LastIndex) = FruitsListbox.RowType.Apple
Me.Rowpicture = DrawApple()
Case IsA Banana
Me.RowTag(Me.LastIndex) = FruitsListbox.RowType.Banana
Me.RowPicture = DrawBanana()
End Select
Next
Such a small amount of rendering shouldn’t be causing that noticeable of an issue, what you’re doing is fine, caching isn’t going to save you that much time.
Listbox size wont matter, the draw calls are only made for what actually fits on the screen.
What is the spec of your machine? CPU, graphics etc.
I only like to say it in rare occasions, have you tried a reboot?
I’d think twice about doing it this way at all
This is very “procedural” approach and a more OO one can make our life a whole lot easier
With the way it is now every time you addd a new fruit you have to
add the fruit (most likely with all public properties so the drawing can access them)
add a method to the listbox to draw that fruit (which means that the listbox has to intimately know the innards which is a bad sign)
update the row type enumeration
It would be better if EVERY fruit knew how to draw itself into the graphics given (and its probably more reusable since the graphics could be from a printer, canvas, etc and each fruit could draw differently if there is enough room)
ie
Class Fruit
Sub Draw(g as graphics)
End Class
Class Banana
Sub Draw( g as graphics)
// whatever a banana needs to do to draw itself
end Sub
End Class
Class Apple
Sub Draw( g as graphics)
// whatever an apple needs to do to draw itself
end Sub
End Class
Then to add a fruit you add a fruit and its specific drawing and your done except for adding instances to the listbox itself
And then your Fruitslitsbox CellBackgroundPaint turns into something simple like
' Background color
g.ForeColor = &cFFFFCC00
g.FillRect(0, 0, g.Width, g.Height)
If row < Me.ListCount Then
Dim aFruit As Fruit = self.RowTag(row)
if aFruit <> nil then aFruit.Draw(g, row = me.listindex) // <<<<<< the magic of polymorphism makes this work !
End If
Return True
And initializing the fruits becomes simple too
Dim apple As Apple
apple = New Apple
apple.MyName = "Granny Smith"
apple.MyWeight = "150 g"
apple.MyColor = "green"
FruitsListbox1.AddRow ""
FruitsListbox1.rowtag(FruitsListbox1.LastIndex) = apple
Dim banana As Banana
banana = New Banana
banana.MyName = "Cavendish"
banana.MyColor = "yellow"
banana.Amount = 12
FruitsListbox1.AddRow ""
FruitsListbox1.rowtag(FruitsListbox1.LastIndex) = banana
apple = New Apple
apple.MyName = "Graham"
apple.MyWeight = "90 g"
apple.MyColor = "yellow/red"
FruitsListbox1.AddRow ""
FruitsListbox1.rowtag(FruitsListbox1.LastIndex) = apple
No need to store the fruits array and the cell tags
Ok, but if I only draw Listboxs background color, it’s also very slow. Only these two lines making the performance also bad:
' Background color
g.ForeColor = &cFFFFCC00
g.FillRect(0, 0, g.Width, g.Height)
Thank you all so much for your input.[quote=352455:@]What is the spec of your machine? CPU, graphics etc.[/quote]
Retina iMac 21,5, 2015, 8GB RAM
Everything you can imagine is possible
You are right! Thanks for your inout, I’ll check this.