listicon gadget speed (with large images, 2000+ items)
listicon gadget speed (with large images, 2000+ items)
I'm having a little problem. In my program I am using a listicon with large images, but I'm finding that on some computers it goes EXTREMELY slow after about 2,000 items. Basically, it would freeze the program. This doesn't happen on my computer as it has pretty high specs, but it happens on slower computers, such as my buddy's laptop. It's really important that I can support a very large list. I was wondering if it's possible to do some sort of optimizations to perhaps load each image in the list on the fly? Or something to that extent? Also, has anyone else bumped into this problem?
Thanks in advance.
Thanks in advance.
- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
Yes, I have watched memory usage, it has worried me a bit, it doesn't rise above 50 megs though.. yet.... The image sizes are all identical size (32x32). What I was thinking was perhaps using a window callback to load only the visible icons and unload the non visible icons, perhaps I can also do the same for the text following the icon. Just not sure how I would do this.
Thanks for the responses
Not sure of the specs, I'll ask him laterWhat is the memory and graphics processor of your buddys laptop?
What CPU )pII, pIII etc( ?
Yes, 32x32Also what size are the image files? Are they consistent?
Not sure why that matters, but they are grabbed from a larger tileset, which is PNG.What format the image files?
Thanks for the responses

I believe rendering 2000+ images from scratch would be a little time comsuming. When I open a directory of lots of images in preview mode, it takes a little while for them all to be available.
Where are they coming from? I wouldn't think disk would be a problem, but on an older slower machine it could have an impact.
You might consider rendering in a thread?
I'm sure the real experts will have some tips. Good luck
cheers,
Where are they coming from? I wouldn't think disk would be a problem, but on an older slower machine it could have an impact.
You might consider rendering in a thread?
I'm sure the real experts will have some tips. Good luck

cheers,
- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
You could use the loading style like in Windows for folders with thumbnail view. The 2000+ items are added right from the beginning. So you have two options now:
1.) Thread Rendering:
In order that the GUI won't freeze and still reacts on user input load all images in the background till it's done and destroy the thread.
2.) Onthefly Rendering:
You calculate how many and wich items are currently in the clipping rect of the gadget and then load the images acordingly.
1.) Thread Rendering:
In order that the GUI won't freeze and still reacts on user input load all images in the background till it's done and destroy the thread.
2.) Onthefly Rendering:
You calculate how many and wich items are currently in the clipping rect of the gadget and then load the images acordingly.
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?
- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
OK so I ask questions... these are PNG, nice format... lossless...
I am thinking you have an ALPHA layer for transparency maybe?
Have you considered JPG?
I know a 32X32 png on my system with NO ALPHA is 1.93k and the exact same JPG is 2.1k... Hmmmm let me cut the PNG to 256 colors and see that as well...
256color PNG at 32X32 is 1.71k... slight savings...
so 2000 of those would take up 3420k more or less.
3.42mb? I must have dropped a 0 somewhere!
Also are all the images the same? As I read this it seems to me the answer must be yes.
You could just load one image and copy it to all new images.

You know this would be a good time to query srod if his esGrid can handle your tasks!
http://www.purebasic.fr/english/viewtopic.php?t=26647
I am thinking you have an ALPHA layer for transparency maybe?
Have you considered JPG?
I know a 32X32 png on my system with NO ALPHA is 1.93k and the exact same JPG is 2.1k... Hmmmm let me cut the PNG to 256 colors and see that as well...
256color PNG at 32X32 is 1.71k... slight savings...
so 2000 of those would take up 3420k more or less.
3.42mb? I must have dropped a 0 somewhere!

Also are all the images the same? As I read this it seems to me the answer must be yes.
You could just load one image and copy it to all new images.

You know this would be a good time to query srod if his esGrid can handle your tasks!
http://www.purebasic.fr/english/viewtopic.php?t=26647
Thanks again for the responses guys. I'm probably going to go with #2 to load and unload the images on the fly, I'm going to fiddle with my code and see if I can figure it out.Fluid Byte wrote:You could use the loading style like in Windows for folders with thumbnail view. The 2000+ items are added right from the beginning. So you have two options now:
1.) Thread Rendering:
In order that the GUI won't freeze and still reacts on user input load all images in the background till it's done and destroy the thread.
2.) Onthefly Rendering:
You calculate how many and wich items are currently in the clipping rect of the gadget and then load the images acordingly.
I love Purebasic.
- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
Well you should be able to see which items are currently selected, but I have been having problems keeping the ListIconGadget set on the last line entered, can't even make that work.
Only thing I can think of is to add 1 to the listicongadget with SetGadgetItemData() by keeping tabs on the #PB_EventType_Change in Event... then you have to assume that is the number of the gadget at the TOP of the ListIconGadget... and ADD your lines displayed from there and display with: SetGadgetItemState() with that number as your new index start...
But I am probably wrong
Quick Question:
Are you using CatchImage(#PB_Any, MemoryAddress) to create copies of this image?
Here I used 3000 48X48 jpg images... works well...
Change the number where indicated and maybe compile different versions of this and test your buddies computer with different image number versions.
Only thing I can think of is to add 1 to the listicongadget with SetGadgetItemData() by keeping tabs on the #PB_EventType_Change in Event... then you have to assume that is the number of the gadget at the TOP of the ListIconGadget... and ADD your lines displayed from there and display with: SetGadgetItemState() with that number as your new index start...
But I am probably wrong
Quick Question:
Are you using CatchImage(#PB_Any, MemoryAddress) to create copies of this image?
Here I used 3000 48X48 jpg images... works well...
Code: Select all
; Shows possible flags of ListIconGadget in action...
UseJPEGImageDecoder()
If LoadImage(0, "resQ0.jpg") ; change path/filename to your own 32x32 pixel image
EndIf
If OpenWindow(0, 0, 0, 640, 300, "ListIconGadgets", #PB_Window_SystemMenu | #PB_Window_ScreenCentered) And CreateGadgetList(WindowID(0))
; left column
ListIconGadget(5, 10, 10, 620, 165, "", 200,#PB_ListIcon_GridLines)
; Here we change the ListIcon display to large icons and show an image
ChangeListIconGadgetDisplay(5, 0)
; AddGadgetItem(5, 1, "Picture 1", ImageID(0))
For X = 0 To 3000 ; change number to test start with 100, then 500, then 1000, then 1500, 2000 3000 etc
AddGadgetItem(5, x, "Picture "+Str(x), ImageID(0))
Next X
Repeat : Until WaitWindowEvent() = #PB_Event_CloseWindow
EndIf

- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
A slightly more complex way:
Well thats all I got on that! You can reference the selected to open a file or do something etc.

Code: Select all
Enumeration
#Window_0
#Text_Selected
#LI_0
EndEnumeration
Global Window_0, ListIcon_0, Text_0, Button_0
Structure VisualDesignerGadgets
Gadget.l
EventFunction.l
EndStructure
Global NewList EventProcedures.VisualDesignerGadgets()
UseJPEGImageDecoder()
If LoadImage(0, "resQ0.jpg") ; change path/filename to your own 32x32 pixel image
EndIf
Procedure LI_0_Event(Window, Event, Gadget, Type)
Debug "#LI_0"
SetGadgetText(#Text_Selected, "")
Result = GetGadgetState(#LI_0)
parsley$ = GetGadgetItemText(#LI_0, Result,0)
SetGadgetText(#Text_Selected, parsley$)
EndProcedure
Procedure RegisterGadgetEvent(Gadget, *Function)
If IsGadget(Gadget)
AddElement(EventProcedures())
EventProcedures()\Gadget = Gadget
EventProcedures()\EventFunction = *Function
EndIf
EndProcedure
Procedure CallEventFunction(Window, Event, Gadget, Type)
ForEach EventProcedures()
If EventProcedures()\Gadget = Gadget
CallFunctionFast(EventProcedures()\EventFunction, Window, Event, Gadget, Type)
LastElement(EventProcedures())
EndIf
Next
EndProcedure
Procedure Open_Window_0()
Window_0 = OpenWindow(#Window_0, 5, 5, 400, 408, "Window 0", #PB_Window_SystemMenu | #PB_Window_SizeGadget | #PB_Window_TitleBar )
If Window_0
If CreateGadgetList(WindowID(#Window_0))
ListIconGadget(#LI_0, 10, 10, 370, 290, "Column1", 100, #PB_ListIcon_GridLines)
RegisterGadgetEvent(#LI_0, @LI_0_Event())
ChangeListIconGadgetDisplay(#LI_0, 0)
TextGadget(#Text_Selected, 10, 310, 370, 20, "", #PB_Text_Center | #PB_Text_Border)
ButtonGadget(#PB_Any, 10, 340, 370, 40, "BIG FAKE BUTTON")
EndIf
EndIf
EndProcedure
Open_Window_0()
For X = 0 To 3006 ; change number to test start with 100, then 500, then 1000, then 1500, 2000 3000 etc
AddGadgetItem(#LI_0, x, "Picture "+Str(x), ImageID(0))
Next X
Repeat
Event = WaitWindowEvent()
Gadget = EventGadget()
Type = EventType()
Window = EventWindow()
Select Event
Case #PB_Event_Gadget
CallEventFunction(Window, Event, Gadget, Type)
EndSelect
Until Event = #PB_Event_CloseWindow
End

- Rook Zimbabwe
- Addict
- Posts: 4322
- Joined: Tue Jan 02, 2007 8:16 pm
- Location: Cypress TX
- Contact:
Well you can store a value in the Gadget (like the position, and retrieve it as well... It will never show to the user.
Let me monkey with my code a second or two...

Well I think you have discovered a new feature request.
I did this to my LI_0 procedure
The Select Type section does work, but ONLY if an item is clicked on by the user... Apparently just dragging the scrollbar is not enough to trigger a change.
So the List is one giant entity.
I suppose the feature request woudl be a way to get the TOP line and the BOTTOM line of a ListIcon_Gadget that are displayed.
@srod! Does eGrid tell you that?
If he doesn't answer you might ask him on the eGrid thread!

Let me monkey with my code a second or two...

Well I think you have discovered a new feature request.
I did this to my LI_0 procedure
Code: Select all
Procedure LI_0_Event(Window, Event, Gadget, Type)
Select Type
Case #PB_EventType_Change
value = value + 3
Debug "VALUE: "+Str(value)
EndSelect
SetGadgetText(#Text_Selected, "")
Result = GetGadgetState(#LI_0)
parsley$ = GetGadgetItemText(#LI_0, Result,0)
SetGadgetText(#Text_Selected, parsley$)
SetGadgetItemData(#LI_0, 1, Value)
EndProcedure
So the List is one giant entity.
I suppose the feature request woudl be a way to get the TOP line and the BOTTOM line of a ListIcon_Gadget that are displayed.
@srod! Does eGrid tell you that?
If he doesn't answer you might ask him on the eGrid thread!

- Fluid Byte
- Addict
- Posts: 2336
- Joined: Fri Jul 21, 2006 4:41 am
- Location: Berlin, Germany
By the way, do you disable redrawing before you add the items?
Windows 10 Pro, 64-Bit / Whose Hoff is it anyway?