Animating a gif W/O using PIL - python-3.x

I am currently trying to make life easier by having the code pull all the frames into my code and execute the animation. My current code is:
import time
from tkinter import *
import os
root = Tk()
imagelist = []
for file in os.listdir("MY-DIRECTORY"):
if file.endswith(".gif"):
imagelist.append(PhotoImage(file=str(os.path.join("MY-DIRECTORY", file))))
# extract width and height info
photo = PhotoImage(file=imagelist[0])
width = photo.width()
height = photo.height()
canvas = Canvas(width=width, height=height)
canvas.pack()
# create a list of image objects
giflist = []
for imagefile in imagelist:
photo = PhotoImage(file=imagefile)
giflist.append(photo)
# loop through the gif image objects for a while
for k in range(0, 1000):
for gif in giflist:
canvas.create_image(width / 2.0, height / 2.0, image=gif)
canvas.update()
time.sleep(0.1)
root.mainloop()
When I try to execute the file it gives me this error which I cannot make sense of.
Traceback (most recent call last):
File "C:/Users/Profile/Desktop/folder (2.22.2019)/animation2.py", line 21, in <module>
photo = PhotoImage(file=imagelist[0])
File "C:\Users\Profile\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3545, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "C:\Users\Profile\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 3501, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "pyimage1": no such file or directory
Note: I am adapting this code to fit my needs I did not write it.
I ran some print statements to verify the pyimage was being uploaded to the array but I cannot figure out why its saying there is no such file or directory if its already uploaded to the array. Can you all please shine some light.

I found that I was creating an unnecessary array of objects lower in the code. giflist[]. I ultimately resolved the issue by removing it and having the loop use the array that was created earlier in the code imagelist. The following code works now.
import time
from tkinter import *
import os
root = Tk()
imagelist = []
for file in os.listdir("My-Directory"):
if file.endswith(".gif"):
imagelist.append(PhotoImage(file=str(os.path.join("My-Directory", file))))
# Extract width and height info
photo = PhotoImage(file="My-Directory")
width = photo.width()
height = photo.height()
canvas = Canvas(width=width, height=height)
canvas.pack()
# Loop through the gif image objects for a while
for k in range(0, len(imagelist)):
for gif in imagelist:
canvas.create_image(width / 2.0, height / 2.0, image=gif)
canvas.update()
time.sleep(0.1)
root.mainloop()

Related

Displaying image using canvas in Python [duplicate]

This question already has answers here:
tkinter canvas image not displaying
(3 answers)
Closed 4 months ago.
I am getting errors when I want to display photos using canvas and Tkinter.
The code runs properly but when I added a few lines to display the image I got error like this
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.10_3.10.2032.0_x64__qbz5n2kfra8p0\lib\tkinter\__init__.py", line 1921, in __call__
return self.func(*args)
File "C:\Users\Kacper\PycharmProjects\kosmos\[w budowie]guicosmoscatalog.py", line 60, in show
photo_display.pack()
AttributeError: 'int' object has no attribute 'pack'
def show(event):
type = clicked.get()
if type == options_list_planets[0]:
#IMAGE DISPLAYING
canvas2 = Canvas(root, width = 400, height = 400, bg='#171717', bd = 0, highlightthickness=0, relief='ridge')
canvas2.pack()
my_img = ImageTk.PhotoImage(Image.open("Merkury.png"))
canvas2.place(relx = 0.05, rely = 0.1, relheight = 0.6, relwidth = 0.5)
photo_display = canvas2.create_image(225, 210, image=my_img)
photo_display.pack()
#LINES OF CODE RESPONSIBLE FOR DISPLAYING TEXT (IT WORKS)
for widget in pierwszy_frame.winfo_children():
widget.destroy()
for widget in drugi_frame.winfo_children():
widget.destroy()
text_label = tk.Label(pierwszy_frame, text = FULL_MERCURY_DESC)
text_label.pack()
#text2_label = tk.Label(drugi_frame, text = MERCURY_FACT)
#text2_label.pack(side = 'left')
When you create an object on a canvas, it's not a widget and can't be treated as a widget. When you call canvas2.create_image(225, 210, image=my_img), tkinter is going to put the image on the canvas at the given location and then return an integer representing the id of the image.
You are then trying to call pack on this integer, which gives the error 'int' object has no attribute 'pack'
The simply solution is to remove that line of code.
You are also making a very common mistake: you are storing the image reference in a local variable. Python will destroy this variable when the function returns. In order for the image to not be destroyed it needs to be saved as a global variable or as an attribute of some object.
For example, you could attach the image to the canvas2 object like so:
canvas2.my_img = my_img
This is arguably a design flaw in tkinter, but the solution is simple so it's easy to work around.

NameError: name 'Ptime' is not defined using tkinter scale scroller

I'm trying to create a function to modify the timecode shift of a script for instant replay, but when I create the function including the variable mentioned by Tkinter, I'm getting a name not defined error. I used a software called "PAGE" to create the GUI so I really have a very basic knowledge of tkinter. I'm not quite sure what code I need to include so I'm just going to paste all of the function definition and the entire support script generated by PAGE
I moved all of my function definitions into the support script but to no avail
def set_Tk_var():
global Ptime
Ptime = tk.DoubleVar()
global Pspeed
Pspeed = tk.StringVar()
text = "play: timecode: 00:00:0" + str(Ptime) + ";00 \\nc"
def IRplay():
print('testguiPAGE_support.IRplay')
session.write(b"stop\n")
session.write( text.encode() )
sys.stdout.flush()
in the main script the only place it's being referred to is:
def vp_start_gui():
global val, w, root
root = tk.Tk()
testguiPAGE_support.set_Tk_var()
top = Toplevel1 (root)
testguiPAGE_support.init(root, top)
root.mainloop()
w = None
def create_Toplevel1(root, *args, **kwargs):
global w, w_win, rt
rt = root
w = tk.Toplevel (root)
testguiPAGE_support.set_Tk_var()
top = Toplevel1 (w)
testguiPAGE_support.init(w, top, *args, **kwargs)
return (w, top)
getting error
Traceback (most recent call last):
File "C:\Users\InstSmart\Desktop\Rplay\Outputs\testguiPAGE.py", line 23, in <module>
import testguiPAGE_support
File "C:\Users\InstSmart\Desktop\Rplay\Outputs\testguiPAGE_support.py", line 40, in <module>
text = "play: timecode: 00:00:0" + str(Ptime) + ";00 \\nc"
NameError: name 'Ptime' is not defined
if there is anymore info you need, comment it, and I will add to the question

raspberry pi3 b+ slideshow program not working

I wanted to turn my raspberry pi into a slideshow device but I barely know python 3 could anyone help me fix this code I found online? It's supposed to display the images in the list I created but it doesn't run. The only changes I made to this code was the creation of the list so I have no idea why it does not work. The error I'm getting is
Traceback (most recent call last):
File "bro.py", line 82, in <module>
slideshow.start()
File "bro.py", line 56, in start
self.main()
File "bro.py", line 48, in main
self.set_image()
File "bro.py", line 42, in set_image
self.image_name = next(self.images)
StopIteration
Here is the code:
#!/usr/bin/env python3
"""Display a slideshow from a list of filenames"""
import os
import tkinter
from itertools import cycle
from PIL import Image, ImageTk
class Slideshow(tkinter.Tk):
"""Display a slideshow from a list of filenames"""
def __init__(self, images, slide_interval):
"""Initialize
images = a list of filename
slide_interval = milliseconds to display image
"""
tkinter.Tk.__init__(self)
self.geometry("+0+0")
self.slide_interval = slide_interval
self.images = images
self.set_images(images)
self.slide = tkinter.Label(self)
self.slide.pack()
def set_images(self, images):
self.images = cycle(images)
def center(self):
"""Center the slide window on the screen"""
self.update_idletasks()
w = self.winfo_screenwidth()
h = self.winfo_screenheight()
size = tuple(int(_) for _ in self.geometry().split('+')[0].split('x'))
x = w / 2 - size[0] / 2
y = h / 2 - size[1] / 2
self.geometry("+%d+%d" % (x, y))
def set_image(self):
"""Setup image to be displayed"""
self.image_name = next(self.images)
filename, ext = os.path.splitext(self.image_name)
self.image = ImageTk.PhotoImage(Image.open(self.image_name))
def main(self):
"""Display the images"""
self.set_image()
self.slide.config(image=self.image)
self.title(self.image_name)
self.center()
self.after(self.slide_interval, self.start)
def start(self):
"""Start method"""
self.main()
self.mainloop()
if __name__ == "__main__":
slide_interval = 2500
# use a list
images = [
"/~/definitely/1550099164562.png",
"/~/definitely/1550770995551.png",
"/~/definitely/1550771217013.png",
"/~/definitely/1550771726391.jpg"]
# all the specified file types in a directory
# "." us the directory the script is in.
# exts is the file extentions to use. it can be any extention that pillow supports
# http://pillow.readthedocs.io/en/3.3.x/handbook/image-file-formats.html
import glob
images = glob.glob("*.jpg")
path = "."
exts = ["jpg", "bmp", "png", "gif", "jpeg"]
images = [fn for fn in os.listdir(path) if any(fn.endswith(ext) for ext in exts)]
# start the slideshow
slideshow = Slideshow(images, slide_interval)
slideshow.start()
Try next(iter(images)) instead of next(images).
BTW, I have Raspberry Pi slideshows for both Tkinter and Kivy on my tachyonlabs GitHub ... they also download photos from Instagram, but if you don't hook that up or there's no Internet connection they will just cycle through the images in the image directory you specify, with your chosen order and duration.

_tkinter.TclError: image "\full\directory\link.gif" doesn't exist

I'm sorry to be a pain, and I know that there are god knows how many other questions referring to this 'image doesn't exist' tkinter error, however, none of the ones that I have found appear to have an issue with the entire directory, they all seem to just be referring to the file name only.
So, I'm trying to make a Logo Quiz, (I have removed some irrelevant code from the example because otherwise it will be too long to place here..)
However, when I try to show the logo, it tells me that the image doesn't exist.
Showing me an issue with the entire directory link, of which if I copy directly from the error and place into Windows Explorer, opens the image perfectly fine.
Here's the code:
from tkinter import *
import tkinter.messagebox
import random
from PIL import Image, ImageTk
import os
class Window(Frame):
global questionstart
def questionstart():
if gameplayvar == 0:
chosenlinknumber = random.randint(0, len(templist)-1)
chosen = templist[chosenlinknumber]
temp = chosen.split("\\")
temp2 = temp[2].split(".")
temp3 = temp2[0].split("L")
global directory
quizlogo_label = Label(root, image = directory)
quizlogo_label.grid(row=1, column=2)
root = Tk()
root.geometry("900x590")
root.iconbitmap(r'\\replacing\the\server\directory\Documents\pythontests\Logos\logoquizlogo_YVp_icon.ico')
C = Canvas(root, bg="blue", height=500, width=500)
possiblelinks = [
'\\NewLogos\AdobeLogo.gif',
'\\NewLogos\AmazonLogo.gif',
'\\NewLogos\AppleLogo.gif',
'\\NewLogos\BMWLogo.gif',
'\\NewLogos\ChromeLogo.gif',
'\\NewLogos\DebianLogo.gif',
'\\NewLogos\DiscordLogo.gif',
'\\NewLogos\FirefoxLogo.gif',
'\\NewLogos\GoogleLogo.gif',
'\\NewLogos\MicrosoftLogo.gif',
'\\NewLogos\OperaLogo.gif',
'\\NewLogos\PhotoshopLogo.gif',
'\\NewLogos\PlayStationLogo.gif',
'\\NewLogos\PythonLogo.gif',
'\\NewLogos\TwitterLogo.gif',
'\\NewLogos\VisualStudioCodeLogo.gif',
'\\NewLogos\WindowsLogo.gif'
]
templist = possiblelinks
chosenlinknumber = random.randint(0, len(templist)-1)
chosen = templist[chosenlinknumber]
p1 = '\\replacing\the\server\directory\Documents\pythontests'
directory = p1+chosen
app = Window(root)
root.mainloop()
And this is what is returned when I run it:
"C:\Program Files (x86)\Python36-32\python.exe" "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py"
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
return self.func(*args)
File "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py", line 143, in quizstart
questionstart()
File "//replacing/the/server/directory/Documents/pythontests/tkinterimagetry1.py", line 121, in questionstart
quizlogo_label = Label(root, image = directory)
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 2760, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Program Files (x86)\Python36-32\lib\tkinter\__init__.py", line 2293, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "\\replacing\the\server\directory\Documents\pythontests\NewLogos\DiscordLogo.gif" doesn't exist
I don't have a clue what is causing it to not find the file as the directory that is being giving out as an error works perfectly fine in Windows Explorer..
Thanks,
Xan
this is the problematic part:
global directory
quizlogo_label = Label(root, image = directory)
the Label constructor expects the image to be passed in as an ImageTk Instance, not a string containing the filename.
it needs to be something like:
global directory
self.photo = Image.PhotoImage(directory)
self.image = ImageTk.PhotoImage(self.photo)
quizlogo_label = Label(root, image = self.photo)
note that both instances of image classes as assigned as attributes of self which is the instance of Window so that they are not garbage collected when the function exits

How to make functions that draw lines in canvas (tkinter 3.x) properly

I am making a program that draws a line(you decide where is the beggining and end of it with the sliders/scales), problem is im getting these errors(That i wish i understood) when i press the psy Button(code below the errors) :
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\python351\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/Koteu/PycharmProjects/guji/fsd.py", line 23, in creat
cans.create_line(ar1,ar2,br1,br2)
File "C:\python351\lib\tkinter\__init__.py", line 2331, in create_line
return self._create('line', args, kw)
File "C:\python351\lib\tkinter\__init__.py", line 2319, in _create
*(args + self._options(cnf, kw))))
_tkinter.TclError: bad screen distance ".14855536.14855504"
Process finished with exit code 0
anyways, the code :
import os
import sys
from tkinter import *
root = Tk()
app=Frame(root)
root.geometry("1200x1200")
ar1 = Scale(root,from_=0,to=600)
ar2= Scale(app,from_=0,to=600,deafultvar=0)#app instead of root because the button for unknown to me reason
#wouldn't appear in GUI otherwise
br1= Scale(root,from_=0,to=600)
br2= Scale(root,from_=0,to=600)
cans = Canvas(root,width = 500,height = 500)
cans.create_line(600,50,0,50) #This has nothing to do with the actual program by my understanding
def creat():
cans.create_line(ar1,ar2,br1,br2)#< this is what causes the problem i don't understand
psy=Button(root,command=creat,text="karole")
psy.pack()
cans.pack()
ar1.pack()
ar2.pack()
br1.pack()
br2.pack()
mainloop()
also, if that helps, im using py345
cans.create_line(x0, y0, ...) takes an even number of integer coordinates as positional args. You passed widgets, which were turned into their string identifiers. In ".14855536.14855504", '.' represents root, '14855536' is the canvas, and '14855504' is the scale ar1. Instead you need to use the .get() method on the scales to get their integer values. The following works.
from tkinter import *
root = Tk()
root.geometry("1200x1200")
ar1 = Scale(root,from_=0,to=600)
ar2= Scale(root,from_=0, to=600)
br1= Scale(root,from_=0, to=600)
br2= Scale(root,from_=0, to=600)
cans = Canvas(root, width=500, height=500)
def creat():
cans.create_line(ar1.get(), ar2.get(), br1.get(), br2.get())
psy=Button(root, command=creat, text="karole")
ar1.pack()
ar2.pack()
br1.pack()
br2.pack()
psy.pack()
cans.pack()
root.mainloop()
A couple of other fixes: the defaultvar option is not valid and caused an error; mainloop() instead of root.mainloop() caused tk to create a second Tk object, which is a bad idea.
EDIT: added the code that works.

Resources