0

I am trying to thread gif animation which I put in a label Tkinter widget and a progressbar so that they run at the same time when the script is executed. Thereafter, I would like to use the time.sleep(10) to have them run at the same time for 10 seconds then have the progressbar stop using progressbar.stop(). My code is below:

import tkinter
from tkinter import ttk
from tkinter import *
import time
from PIL import Image, ImageTk
from itertools import count
import threading


def main_fun():

    global progressbar, lbl
    window = tkinter.Tk()
    window.geometry("390x600")  # Width x Height

    # progress bar
    progressbar = ttk.Progressbar(None)  # ttk is method inside tkinter
    progressbar.config(orient="horizontal",
                       mode='indeterminate', maximum=100, value=0)
    progressbar.pack(side=TOP)

    # gif image class
    class ImageLabel(tkinter.Label):
        """a label that displays images, and plays them if they are gifs"""

        def load(self, im):
            if isinstance(im, str):
                im = Image.open(im)
            self.loc = 0
            self.frames = []

            try:
                for i in count(1):
                    self.frames.append(ImageTk.PhotoImage(im.copy()))
                    im.seek(i)
            except EOFError:
                pass

            try:
                self.delay = im.info['duration']
            except:
                self.delay = 100

            if len(self.frames) == 1:
                self.config(image=self.frames[0])
            else:
                self.next_frame()

        def unload(self):
            self.config(image=None)
            self.frames = None

        def next_frame(self):
            if self.frames:
                self.loc += 1
                self.loc %= len(self.frames)
                self.config(image=self.frames[self.loc])
                self.after(self.delay, self.next_frame)

    lbl = ImageLabel(window)
    lbl.pack(anchor="center")
    lbl.load(
        'C:/Users/*****/test.gif')

    # thread the label with the gif
    t = threading.Thread(target=lbl, args=(None,))
    t.start()

    window.mainloop()


main_fun()


progressbar.start(8)  # 8 is for speed of bounce
t = threading.Thread(target=progressbar, args=(None,)
                     )  # thread the progressbar
#t.daemon = True
t.start()

time.sleep(10)  # 10 second delay, then progressbar must stop
progressbar.stop()

I am not familiar with threading and so I don't understand what I'm doing wrong. I get the errors:

TypeError: 'ImageLabel' object is not callable

TypeError: 'progressbar' object is not callable

Please assist.

Community
  • 1
  • 1
Kusi
  • 785
  • 1
  • 10
  • 21
  • The `foo` part of the `target=foo` argument for `threading.Thread()` is the function you want to be run in a separate thread. So passing `lbl` or `progressbar` means that those will be called as if they are functions. Thus you are getting those errors. It seems like you didn't read the threading documentation - specifically, what the arguments of `threading.Thread()` are for. – Random Davis Mar 28 '19 at 15:29
  • I saw the `threading.Thread()` in the documentation, but is there a way to use it for tkinter widgets? @RandomDavis – Kusi Mar 28 '19 at 15:38
  • Well sure, you could have the thread consist of a function that updates the given Tkinter widget. Just passing the whole widget object doesn't make sense, since you're not specifying to anything what to actually do with the widget. – Random Davis Mar 28 '19 at 16:08
  • @Kusi: Read, **why** does `time.sleep(...` blocks the `tk.mainloop()` [tkinter-understanding-mainloop](https://stackoverflow.com/questions/29158220/tkinter-understanding-mainloop) – stovfl Mar 28 '19 at 16:47

1 Answers1

1

You can use the answer given here to implement the progress bar on another thread. Also, what was wrong with what you did is that your progressbar isn't a callable object, nor does it override the run() method.

Olivier Samson
  • 609
  • 4
  • 13
  • Thank you, I got it to work by making some modifications to the code in the link you provided. – Kusi Apr 01 '19 at 07:14