0

My objective is to have a looping background image set, functioning exactly the way a .gif does, and on top of that, to have a slideshow of images loop concurrently with a delay of about 1 second.

Originally, when my slideshow was only 150-200 images long, it was no problem to use the following code at launch and deal with a slight delay.

my_photoimage_list = [(PhotoImage(file=image))
                          for image in imagelist]

However, once I imported the remaining thousands of my images, I receive an insufficient memory error. I can get around this using the following code, but I run into a minor bug where the gif background will stop loading momentarily while it waits for the image to be loaded.

My question is this; how can I keep my background image updating at a regular speed while my foreground image cycles through thousands of images? The code below nearly fulfills this task, minus the slight delay when loading larger image sizes.

from tkinter import *
from itertools import cycle
from glob import glob
from random import shuffle

class MyTkinterFrame(Frame):
    def __init__(self, master, image_files):
        self.master = master
        self.x_center = int(self.master.winfo_screenwidth()*.5)
        self.y_center = int(self.master.winfo_screenheight()*.5)
        self.bg = Canvas(self.master)
        self.bg.pack(fill=BOTH, expand=YES)

        self.make_gif()
        self.make_picture(image_files)

        self.updatepicture()
        self.updategif()


    def make_gif(self):
        imagelist = glob('Images/My Tkinter Background/*.gif', recursive=True)
        self.giflist = [(PhotoImage(file=image))
                          for image in imagelist]
        self.gifcycle = cycle(self.giflist)
        self.bg_image=next(self.gifcycle)
        self.bg.gif_create = self.bg.create_image(self.x_center, self.y_center, image=self.bg_image)

    def make_picture(self,image_files):
        self.image_files = cycle(image_files)
        self.slides = PhotoImage(file=next(self.image_files))
        self.img_object = self.slides   
        self.bg.fg = self.bg.create_image(self.x_center, self.y_center, image=self.img_object)



    def updatepicture(self):   #this function loops to update foreground image
        self.img_object = self.slides
        self.bg.itemconfig(self.bg.fg, image=self.img_object)
        self.slides = PhotoImage(file=next(self.image_files))

        #for more pronounced error effect, lower delay(500) to 100
        self.master.after(500, self.updatepicture)


    def updategif(self):       #this function loops to update background image
        self.bg_image=next(self.gifcycle)
        self.bg.itemconfig(self.bg.gif_create, image = self.bg_image)
        self.master.after(25, self.updategif)



if __name__ == '__main__':

    #this bit makes it pretty and easier to diagnose
    root = Tk()
    width = root.winfo_screenwidth()
    height = root.winfo_screenheight()
    root.geometry('%dx%d' % (width, height))
    root.configure(background="#000000")
    #end

           #find foreground images
    image_files = glob('Images/My Tkinter Foreground/*.png', recursive=True)
    shuffle(image_files)

    e = MyTkinterFrame(root, image_files)
    root.mainloop()
suscat
  • 61
  • 8
  • It is not wise to load thousands of images into memory once. Just keep the image filenames in list and create the image when needed. – acw1668 Dec 14 '18 at 03:15
  • Yes that's exactly what I'm doing. At any given time I have no more than 11 images loaded at once, where 10 of them are the looping background images and the other one is the foreground image. The problem is that loading the foreground image halts the .itemconfig update in the background image – suscat Dec 15 '18 at 02:30

0 Answers0