How can I periodically change a tkinter image?
Asked Answered
T

1

3

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.

Tunable answered 24/7, 2016 at 12:35 Comment(4)
Just create a callback on a timerAryn
@PadraicCunningham could you please give an example or explain a bit more. I'm new to this.Tunable
root.after(500, your_function), where you function adds the imageAryn
https://mcmap.net/q/263442/-python-tkinter-label-redrawing-every-10-secondsAryn
I
8

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()
Indocile answered 24/7, 2016 at 18:39 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.