0

I pull data from the internet and display it on canvas. A little time passes while the data is being taken, I want to show a loading animation or a progressbar on the canvas. In theory I managed to do it, it should work when progressbar starts pulling data and stop after data is pulled but it doesn't work. What should I do?

from tkinter import*
from tkinter import ttk
import io
from PIL import Image, ImageTk
import requests
from urllib.request import urlopen


class Root(Tk):
    def __init__(self):
        super().__init__()
        
        self.canvas =Canvas(
        width = 720, height = 1000)
        self.canvas.place(relx=0,rely=0)
        
        self.button = Button(self, text="Get The Posters",
        command=self.get)
        self.button.pack()
        
        self.movie_list=["Tenet","Memento","Inception"]
        self.poster_list=[]
        self.x=0
        self.count=0
        
        
    def get(self):
        
        self.button.destroy()
        self.label=Label(text="loading")
        self.label.place(relx=0.08,rely=0.65)
        self.pb = ttk.Progressbar(orient='horizontal',
        mode='indeterminate',length=480)
        
        if self.count==0:
            self.pb.place(relx=0.08,rely=0.7)
            self.pb.start()
        
        for i in self.movie_list:
            self.url = "http://www.omdbapi.com/?apikey=73a4d84d&t={}".format(i)
            self.response = requests.get(self.url)
            self.data = self.response.json()
            self.pic_url=self.data["Poster"]
            self.my_page = urlopen(self.pic_url)
            self.my_picture = io.BytesIO(self.my_page.read())
            self.pil_img = Image.open(self.my_picture).resize((200,296))
            self.tk_img = ImageTk.PhotoImage(self.pil_img)
            self.poster_list.append(self.tk_img)
            self.count=1
            
        if self.count==1:
            self.pb.stop()
            
        for n in range(len(self.poster_list)):
            self.x+=30
            if n==1:
                self.x+=200
            if n==2:
                self.x+=200
            self.canvas.create_image(
            self.x,100,image=self.poster_list[n],anchor=NW)

root = Root()
root.mainloop()
newfile.py
  • 33
  • 4
  • tkinter does not have the control during `get()` is being executed, so the progress bar will not be shown and updated until `get()` exits. – acw1668 Sep 30 '21 at 10:16
  • @acw1668 I understand, thanks, but is there any other way? – newfile.py Sep 30 '21 at 10:27
  • One way is to call `self.update_idletasks()` after `self.count=1` inside the for loop. Another way is to refactor your code to run the for loop in a child thread. – acw1668 Sep 30 '21 at 10:32
  • @acw1668 Thanks for your interest but I failed. – newfile.py Sep 30 '21 at 13:32
  • See [my answer to another question](https://stackoverflow.com/a/69202749/5317403) as an example. – acw1668 Sep 30 '21 at 16:19
  • @acw1668 As you said, I looked at your other answer and managed to integrate it for myself after struggling until morning. It's working fine for now. Endless thanks to you. – newfile.py Oct 01 '21 at 06:58

1 Answers1

0

The reason why the program didn't work was because the functions were running in order. It worked when I ran the functions simultaneously using 'threading'.

from tkinter import*
from tkinter import ttk
import io
from PIL import Image, ImageTk
import requests,threading
from urllib.request import urlopen


class Root(Tk):
    def __init__(self):
        super().__init__()
        
        self.canvas =Canvas(
        width = 720, height = 1000)
        self.canvas.place(relx=0,rely=0)
        
        self.button = Button(self, text="Get The Posters",
        command=self.play)
        self.button.pack()
        
        self.movie_list=["Tenet","Memento","Inception"]
        self.poster_list=[]
        self.x=0
        self.label=Label(text="loading...please wait...")
        self.pb = ttk.Progressbar(orient='horizontal',mode='indeterminate',length=480)
        
    def animation(self):
        self.button.destroy()
        self.label.place(relx=0.5,rely=0.85,anchor='c')
        self.pb.place(relx=0.5,rely=0.9,anchor='c')
        self.pb.start()
        
    def play(self):
        self.t1 = threading.Thread(target=self.animation)
        self.t2 = threading.Thread(target=self.get_posters)
        self.t1.start()
        self.t2.start()
            
    def get_posters(self):
        
        for i in self.movie_list:
            self.url = "http://www.omdbapi.com/?apikey=73a4d84d&t={}".format(i)
            self.response = requests.get(self.url)
            self.data = self.response.json()
            self.pic_url=self.data["Poster"]
            self.my_page = urlopen(self.pic_url)
            self.my_picture = io.BytesIO(self.my_page.read())
            self.pil_img = Image.open(self.my_picture).resize((200,296))
            self.tk_img = ImageTk.PhotoImage(self.pil_img)
            self.poster_list.append(self.tk_img)
            
        for n in range(len(self.poster_list)):
            self.x+=30
            if n==1:
                self.x+=200
            if n==2:
                self.x+=200
            self.canvas.create_image(
            self.x,100,image=self.poster_list[n],anchor=NW)
            
        self.label.destroy()
        self.pb.destroy()


root = Root()
root.mainloop()
newfile.py
  • 33
  • 4