I would like to add a looping video in a tkinter window. I have seen codes from here in stacksoverflow and online, and they seem to be about a Live Capture Video. in my case, I would like to import a video file to my existing Tkinter window, and if possible, keep it on loop. what modules do I need to import and how do I structure the code properly?
I am gonna add some codes that I have used.. I thankfully give the credits to the original creators whoever they are.
import imageio
from PIL import Image, ImageTk
video_name = "vid.mp4"
video = imageio.get_reader(video_name)
def stream(label):
for image in video.iter_data():
frame_image = ImageTk.PhotoImage(Image.fromarray(image))
label.config(image=frame_image)
label.image = frame_image
if __name__ == "__main__":
root = Tk()
my_label = Label(root)
my_label.pack()
thread = threading.Thread(target = stream, args=(my_label))
thread.daemon = 1
thread.start()
root.mainloop()
Related
I'm new to Python GUI's and am currently trying to build an app with DearPy. I was wondering if it's possible to use an mp4 formatted logo (animated logo) instead of the png logo's it would usually accept. For example:
with window("Appi", width= 520, height=677):
print("GUI is running")
set_window_pos("Appi", 0, 0)
add_drawing("logo", width=520, height=290)
draw_image("logo", "random.png", [0,240])
My question is: would it be possible to change the add_drawing to an add video and then the draw_image to allow me to insert an mp4 instead of a png? I've tried to look through the documentation but haven't found guidance for this yet.
Or is there an alternative package I should be using (i.e. tkinter)?
Thanks!
I used tkinter for this and it worked perfectly fine:
import tkinter as tk
import threading
import os
import time
try:
import imageio
except ModuleNotFoundError:
os.system('pip install imageio')
import imageio
from PIL import Image, ImageTk
# Settings:
video_name = 'your_video_path_here.extension' #This is your video file path
video_fps = 60
video_fps = video_fps * 1.2 # because loading the frames might take some time
try:
video = imageio.get_reader(video_name)
except:
os.system('pip install imageio-ffmpeg')
video = imageio.get_reader(video_name)
def stream(label):
'''Streams a video to a image label
label: the label used to show the image
'''
for frame in video.iter_data():
# render a frame
frame_image = ImageTk.PhotoImage(Image.fromarray(frame))
label.config(image=frame_image)
label.image = frame_image
time.sleep(1/video_fps) # wait
# GUI
root = tk.Tk()
my_label = tk.Label(root)
my_label.pack()
thread = threading.Thread(target=stream, args=(my_label,))
thread.daemon = 1
thread.start()
root.mainloop()
Edit: Thanks <3
Videos are in DearPyGui currently not supported
I've written a bunch of code that produces a GUI. Now whenever I run the code it produces the main GUI window and one additional small window with nothing in it. When I close the smaller window the large main window disappears.
Now I've been reading other posts with similar problems, but I haven't been able to identify where the error is in my code.
Please help :)
Follow up question: How would I add a background image rather than the grey boring color?
Here is what it looks like.
#%% GUI Interface
import Tkinter as tk
from tkFont import Font
from PIL import ImageTk, Image
from Tkinter import END
#This creates the main window of an application
window = tk.Toplevel()
window.title("Sat Track")
window.geometry("1200x800")
window.configure(background='#f0f0f0')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
header = tk.Label(window, text="Satellite Control Center", font=Font(size=40))
header.pack()
toprow = tk.Frame(window)
infobox = tk.Text(toprow, width=50, height=7, font=("Calibri",12))
infobox.pack(side = "left")
infobox.insert(END,"Current information for:"+spacer+name +'\n'+
"Time:" +space+times+ '\n'+
"Longitude:"+space +x_long+ '\n'+
"Latitude:" +space+x_lat+ '\n'+
"Altitude:" +space+alt+space+ "[km]"+'\n'+
"Velocity:" +space+vel+space+ "[km/s]" + '\n'+
"Spatial Resolution: "+space +spat+space+ "[Pixels pr. m]"
)
toprow.pack()
midrow = tk.Frame(window)
globeview = tk.Label(midrow, image = img1)
globeview.pack(side = "left") # the side argument sets this to pack in a row rather than a column
mercatorview = tk.Label(midrow, image = img2)
mercatorview.pack(side = "left")
midrow.pack() # pack the toprow frame into the window
bottomrow = tk.Frame(window)
currentweather= tk.Label(bottomrow, image = img3)
currentweather.pack(side = "left")
gearth = tk.Label(bottomrow, image = img4)
gearth.pack(side = "left")
bottomrow.pack()
#Start the GUI
window.mainloop()
Every tkinter application needs exactly one instance of Tk class. In your code you don't create one but mainloop seem to create one automatically it's still created (See Bryan's comment below), even though you can't(easily) refer to it later.
If you will use additional Toplevel widgets to that of your curent one go:
root = tk.Tk()
root.withdraw() # You can go root.iconify(), root.deiconify() later if you
# want to make this window visible again at some point.
# MAIN CODE HERE
root.mainloop()
if not simply replace:
window = tk.Toplevel()
with:
window = tk.Tk()
Note: Also note that if you're working using IDLE keep in mind that it creates its own Tk object which may hide the fact that your application will need one when used standalone.
Remove Toplevel from window = tk.Toplevel(). I don't have a python2 dist available -- I'm on python3 but when I removed TopLevel from my code, it only brought up one window. So, the python3 way is....
import tkinter as tk
#This creates the main window of an application
window = tk.Tk()
#Start the GUI
window.mainloop()
I think the only difference would be that python2's tkinter is actually Tkinter (as you have already done).
I have some trouble at showing Tkinter + PIL image on the Windows Task Scheduler. It is works flawlessly when i compile using CMD, but the image won't appear on Task Scheduler.
Here is some of my simple code:
import Tkinter as tk
import time
from PIL import ImageTk, Image
def close():
global root
root.quit()
return;
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open('C:\xxx\xxx\Desktop\RedAlert.jpg'))
def alert():
global img
panel = tk.Label(root, image = img, height=2000, width=2000)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root.after(10*500, root.destroy)
root.mainloop()
count = 0
while(count < 3):
count = count+1
time.sleep(1)
if count == 2:
alert()
print count
I am using Windows 10. I also have tried to some Wav Sound with this code and some blink LED using arduino by serial. Everything works fine either on CMD and Windows Task Scheduler, except for the Image it's never pop up on The Task Sch.. I have tried to save in pyw, Bat, but still not working. Please Help me guys. :(
I'm using python3 and tkinter, the first code works but the second after I put it into a function it no longer shows the image and I want to know why
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("test")
canv = Canvas(root,width=500, height=500)
canv.pack()
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.create_image(0,0,anchor="nw",image=image)
root.mainloop()
second code:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("test")
def main():
canv = Canvas(root,width=500, height=500)
canv.pack()
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.create_image(0,0,anchor="nw",image=image)
main()
root.mainloop()
In order to properly display ImageTk.PhotoImage images, you need to keep a persistent reference to each of them (see this answer and the documentation).
When your code leaves the main() function, your image object is garbage-collected. One easy way to fix this is to store the image reference in the canvas object, so that it will not be garbage-collected as long as your canvas exists:
...
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.img = image
...
I have an image that is saved in a file test.bmp and this file is overwritten 2 times per second
(I want to show 2 images per second).
Here is what I have so far:
import tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
img_path = 'test.bmp'
img = ImageTk.PhotoImage(Image.open(img_path), Image.ANTIALIAS))
canvas = tk.Canvas(root, height=400, width=400)
canvas.create_image(200, 200, image=img)
canvas.pack()
root.mainloop()
But I don't know how can I refresh the image every ½ second?
I'm using Python3 and Tkinter.
Gee, the code in your question looks very familiar...
Coming up with an answer comprised of tested code was complicated by the need to have the image file be updated by some mysterious unspecified process. This is done in the code below by creating a separate thread that periodically overwrites the image file independent of the main process. I tried to delineate this code from the rest with comments because I felt it was somewhat distracting and makes things seem more complex than they are really.
The main takeaway is that you'll need to use the universal tkinter widget after() method to schedule the image to be refreshed at some future time. Care also needs to be taken to first create a place-holder canvas image object so it can be updated in-place later. This is needed because there may be other canvas objects present, and otherwise the updated image could cover them up depending on relative placement if a place-holder had not been created (so the image object id that's returned can be saved and used later to change it).
from PIL import Image, ImageTk
import tkinter as tk
#------------------------------------------------------------------------------
# Code to simulate background process periodically updating the image file.
# Note:
# It's important that this code *not* interact directly with tkinter
# stuff in the main process since it doesn't support multi-threading.
import itertools
import os
import shutil
import threading
import time
def update_image_file(dst):
""" Overwrite (or create) destination file by copying successive image
files to the destination path. Runs indefinitely.
"""
TEST_IMAGES = 'test_image1.png', 'test_image2.png', 'test_image3.png'
for src in itertools.cycle(TEST_IMAGES):
shutil.copy(src, dst)
time.sleep(.5) # pause between updates
#------------------------------------------------------------------------------
def refresh_image(canvas, img, image_path, image_id):
try:
pil_img = Image.open(image_path).resize((400,400), Image.ANTIALIAS)
img = ImageTk.PhotoImage(pil_img)
canvas.itemconfigure(image_id, image=img)
except IOError: # missing or corrupt image file
img = None
# repeat every half sec
canvas.after(500, refresh_image, canvas, img, image_path, image_id)
root = tk.Tk()
image_path = 'test.png'
#------------------------------------------------------------------------------
# More code to simulate background process periodically updating the image file.
th = threading.Thread(target=update_image_file, args=(image_path,))
th.daemon = True # terminates whenever main thread does
th.start()
while not os.path.exists(image_path): # let it run until image file exists
time.sleep(.1)
#------------------------------------------------------------------------------
canvas = tk.Canvas(root, height=400, width=400)
img = None # initially only need a canvas image place-holder
image_id = canvas.create_image(200, 200, image=img)
canvas.pack()
refresh_image(canvas, img, image_path, image_id)
root.mainloop()