1

I am creating an app that will allow users to scan a ticket and a message will be displayed. I have created a short GIF animation to play when the app starts to show users where to scan their ticket.

I am having trouble understanding how to play a GIF image using tkinter in Python 3. I have tried many solutions and I came across a piece of code where you select the folder and the images in that folder will play in a loop but it's not working.

I think I'm not understanding the code. Here is my code for my app:

from tkinter import *
from tkinter import messagebox
import tkinter.filedialog
from tkinter.filedialog import askdirectory
import requests
import simplejson as json
import os

#from json import JSONEncoder


#class MyEncoder(JSONEncoder):
    #def default(self, o):
         #return o.__dict__    


#Connect to API function

def apiconnect(statusvar):

    ticektid = e1.get()

    def to_serializable(ticketid):
        return str(ticketid)

    url = "https://staging3.activitar.com/ticket_api/tickets"
    data = {'ticket_id':e1.get(),'direction': 'up'}
    headers = {'Content-Type': 'application/json','Authorization' :'J0XDvDqVRy9hMF9Fo7j5'}
    r = requests.post(url,data=json.dumps(data), headers=headers)
    requestpost = requests.post(url, headers=headers, json=data)
    response_data = requestpost.json()
    statusvar = (response_data["status"])
    messagevar = (response_data["message"])
    json.dumps(url,data)
   # MyEncoder().encode(ticketid)
    #'{"ticekt_id": "/foo/bar"}'
#19 February 2018
#def from_json(json_object):
  #  if 'ticket_id' in json_object:
       # return FileItem(json_object['ticket_id'])
       # ticketid = JSONDecoder(object_hook = from_json).decode('{"ticket_id": "/foo/bar"}')

#Including GPIO config 
    if statusvar == "failed":
        messagebox.showinfo("Cape Point", messagevar)

    else: statusvar == "successful"



#Run at full screen automatically:
#---------------Function & Class--------------------------------#
class FullScreenApp(object):
    def __init__(self, master, **kwargs):
        self.master=master
        pad=3
        self._geom='200x200+0+0'
        master.geometry("{0}x{1}+0+0".format(
            master.winfo_screenwidth()-pad, master.winfo_screenheight()-pad))
        master.bind('<Escape>',self.toggle_geom)            
    def toggle_geom(self,event):
        geom=self.master.winfo_geometry()
        print(geom,self._geom)
        self.master.geometry(self._geom)
        self._geom=geom
#--------------------------------------------------------------------#

        def next_img():
            img_label.img = PhotoImage(file=next(imgs))
            img_label.config(image=img_label.img)

#create a textbox on a form
root = Tk()

#-----Full Screen-------#
app = FullScreenApp(root)


root.title("Cape Point")
root.configure(background = 'White')

#________ this code below was the original that displayed a static image _____#

#titlepic = PhotoImage(file = "ScanPlease.gif")         
#shownpic = titlepic
#filename = shownpic
#Label(root, image = filename).grid(row=0, sticky=W)

img_dir = askdirectory(parent=root, initialdir= "C:/Users/Nickitaes/Desktop", title='Where To Scan')
os.chdir(img_dir)
imgs = iter(os.listdir(img_dir))

img_label = Label(root)
img_label.bind("<Return>",next_img())

next_img()

e1 = Entry(root)


e1.grid(row=1, column=0)
e1.focus_set() #set cursor focus to textbox

e1.bind("<Return>", apiconnect) #Return function


root.mainloop( )

Thanks for the help!

1 Answers1

0

Well..., it was not hard to find other questions about this on StackOverflow. Here are some: Play Animations in GIF with Tkinter and Play an Animated GIF in python with tkinter.

I have combined the answers to take care of different number of subpictures an also commented the code a bit more.

from tkinter import *
import time

root = Tk()

framelist = []          # List to hold all the frames
for ix in range(1000):  # range > frames in largest GIF
    part = 'gif -index {}'.format(ix)
    try: frame = PhotoImage(file='giphy.gif', format=part)
    except:
        last = len(framelist) - 1   # Save index for last frame
        break           # Will break when GIF index is reached
    framelist.append(frame)

def update(ix):  
    if ix > last: ix = 0    # Reset frame counter if too big
    label.configure(image=framelist[ix]) # Display frame on label
    ix += 1                 # Increase framecounter
    root.after(100, update, ix) # Run again after 100 ms.

label = Label(root)
label.pack()
root.after(0, update, 0)    # Start update(0) after 0 ms.
root.mainloop()

Adjust the for-loop for the GIF size you use, or rewrite as a while-loop.

I don't know how to read the frame delay from the GIF. You'll have to try different values in after() until it looks good.

figbeam
  • 7,001
  • 2
  • 12
  • 18