Best way to load a bunch of images

I have 12 800x600 jpg images I want to load and have ready when the page Shown event fires. I have read the “User Guide - Framework” and it says the best way to do this is “…simply assign the picture to a property of the web page…” which is what I plan to do.

What I am wondering is if It would be better to do this before the command to show the page (WebPage1.Show) is sent. Here’s why. I have a web page with a picture that loads fine if I put the url to the picture in the Open event, but if I put it in the Shown event it doesn’t show up. It just loads a spacer.gif (which is what I assume is the default if you don’t specify anything in the Inspector which is the case for me; I want to specify a path at runtime so I can’t put it in the url in the Inspector). Seems like a timing issue.

Would it be better to load the images when the session starts? Is there an easy way for the program to “know” when it is done loading the images?

Let me know if this doesn’t make sense.

The Open event fires before the page is sent to the client browser. The Shown event fires after it has been sent and rendered by the client browser. Setting WebImageView.Picture or WebImageView.URL in Shown should work, but you are changing the page content after it has loaded so there may be a visible delay. I just tested this myself and for some reason it does not work. I believe that’s a bug but I do not know if it has been reported yet.

Setting these properties in Open, or presetting them in the IDE, causes the client browser to start loading the picture as it’s rendering the page. There may still be a delay for large pictures and/or slow connections. But there’s not the added delay of waiting for the initial page load; performing an event round trip to the server; and then finally starting the image download. I just tested this as well and it works fine.

A lot of control manipulation has to be done in Shown after the page has loaded on the client. But I think setting the picture is something you want to do in Open.

WebPicture.Cached tells you if a picture is already loaded on the client browser. I haven’t tried this, but I think you can load up some WebPictures in an array property of the page; check their Cached status with a Timer; and do something (i.e. actually display them) once they’re all loaded. Web Custom Controls has an image loader that let’s you explicitly send images to the client browser, and will raise an event for each picture when it has finished loading. A little more convenient.

Also…it has been a while since I’ve run this test, but in Real Studio WE I found that image loading performance was better using URLs with WebImageView and letting another server app (i.e. Apache) serve the images, even if it was on the same server hardware. My client was loading a page with photos (think something like Flickr) so it mattered, though it probably doesn’t matter for most web apps.

If those 12 images are the same for all sessions I’d load them into memory in the App.Run event. That way you’ll only end up with 12 images for the entire app rather than 12 images per session which could blow the runtime memory.

Wow! Both of these answers are absolutely great. Thank you Daniel and Wayne. I wish I could give you both credit for answering but I don’t think that’s possible.

Can I get an example that preloads an image in the App.Open event?

I put a public property p (as a WebImageView) in App and then load url in p like this p.url = JPGPath +“filename.jpg”. JPGPath is defined in a Global property in a Module but not sure it is available to App.Open event. When I run it, it doesn’t crash but I can’t figure out how to use it in the app. I would verify if JPGPath is available but MsgBox didn’t work in App.Open event.

[Note: Putting p.url = JPGPath +“filename.jpg” in Open event crashes with NilObjectException.]

Just curious: Why doesn’t a MsgBox in App.Open event work?

You would store a picture object* in a WebPage property to have it cached locally in the browser. A WebImageView is a control for displaying pictures that is placed on your WebPage and referenced by name. It is not usually stored in a property and referenced that way.

  • The docs do not make it clear if the object has to be a WebPicture or if it can be a generic Picture. My suspicion is WebPicture. Regardless, you are dealing with images at external URLs and not with images in Xojo itself, so the caching suggestion does not apply.

You received the NilObjectException because you tried to use the property but there was nothing in it, i.e. you did not create a WebImageView and store it in the property first. (But again this would not normally be done.)

If you have image URLs rather then Xojo picture objects, then simply set the URL property of the WebImageView control on your WebPage. Either preset it in the IDE or set it in Open. Again, this is not a WebImageView property, but the actual control you drag to your page. Setting it in Open does not guarantee that the image will be downloaded when Shown fires. The client browser may still be downloading and waiting to display the image at that time. But Open is where you want to set it if you do not preset it in the IDE.

I do not know if there’s a way with the current version of Xojo to make sure that all of your image URLs have downloaded before doing something like starting a slideshow (i.e. changing WebImageView.URL every X seconds). WebImageLoaderTD in my Web Custom Controls toolkit does exactly that with external image URLs as well as Xojo WebPictures. If you were using that you would ask it to load the dozen URLs in Shown (not Open because it has to be loaded itself to work) and then you would start your slideshow after receiving event notifications that each image had loaded. The demo at my site illustrates this by dowloading 4 images with a progress bar, and then allowing you to switch between them. By downloading them first there is no delay when moving Next.

Because there is no web page yet in the client browser. Open fires before anything has been sent to the client.

Correction to my above post: in App.Open there is no web page at all, so there is no where to display a message box. App.Open fires when the application launches, not when a client connects.

Using MsgBox in WebPage.Open actually does work. Still keep in mind that at WebPage.Open the page has not actually been sent to the client browser. A lot of things will not work there and have to be done in Shown. But some do, and MsgBox is one of them.