Python Forum
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
rotating image with Tkinter
#1
Hi,

I am trying to rotate images on canvas using Tkinter after() method.

My images dont appear in the window and they dont seem to rotate. I get an error message:

Error:
invalid command name "3064880984move" while executing "3064880984move" ("after" script)
Here's the code:

from tkinter import *
from PIL import Image, ImageTk

ws = Tk()
ws.title('PythonGuides')


#ws.geometry("800x1000")

l = Label(ws, font = "bold")
l.pack()



x = 1

def move():
    global x
    if x == 3:
       x = 1
    if x == 1:
        img = PhotoImage(file='/home/pi/Desktop/sasuke.png')
        Label(ws, image=img).pack()
    elif x ==2:
        img2 = PhotoImage(file='/home/pi/Desktop/3.png')
        Label(ws, image=img2).pack()
    elif x ==3:
        img3 = PhotoImage(file='/home/pi/Desktop/Master-Warning-Light.png')
        Label(ws, image=img3).pack()

    x+=1
    
    ws.after(2000,move)
    
move()



ws.mainloop()
Anyone familiar with that type of error?

Thank you
Reply
#2
Here is a very simple example of tkinter image slideshow. Compare it to your code.
Frankduc likes this post
Reply
#3
oh thank you Gribouillis
it works!
Reply
#4
Do you have any idea why your program didn't work?

I cleaned up your program a little and ran it..
import tkinter as tk

image_files = [
    "dice1.png",
    "dice2.png",
    "dice3.png",
    "dice4.png",
    "dice5.png",
    "dice6.png",
]
ws = tk.Tk()
l = tk.Label(ws, font="bold")
l.pack()
index = 0

def move():
    global index
    img = tk.PhotoImage(file=image_files[index])
    tk.Label(ws, image=img).pack()
    index = (index + 1) % len(image_files)
    ws.after(2000, move)

move()

ws.mainloop()
When I run this program I don't see any images. The window also gets taller every two seconds.

I remember reading something about images in tkinter buttons and labels. tkinter doesn't keep a reference to the image, leaving that to your program. If you don't keep a reference to the image the reference count drops to zero and the image is marked for disposal. When the image is garbage collected it cannot be drawn. I modify my program to keep a refence to the image.
import tkinter as tk

image_files = [
    "dice1.png",
    "dice2.png",
    "dice3.png",
    "dice4.png",
    "dice5.png",
    "dice6.png",
]
ws = tk.Tk()
l = tk.Label(ws, font="bold")
l.pack()
index = 0


def move():
    global index
    global img   #  This keeps the image in a global variable.  I should see images now.
    img = tk.PhotoImage(file=image_files[index])
    tk.Label(ws, image=img).pack()
    index = (index + 1) % len(image_files)
    ws.after(2000, move)


move()

ws.mainloop()
When I run this program I see an image, but the window is still growing every two seconds. That is probably caused by creating and packing a new Label object each time I change the image. I am going to change my program to reuse the same label.
import tkinter as tk

image_files = [
    "dice0.png",
    "dice1.png",
    "dice2.png",
    "dice3.png",
    "dice4.png",
    "dice5.png",
    "dice6.png",
]
ws = tk.Tk()
image_label = tk.Label(ws, font="bold")
image_label.pack()
index = 0


def move():
    global index
    global img
    img = tk.PhotoImage(file=image_files[index])
    image_label["image"] = img
    index = (index + 1) % len(image_files)
    ws.after(2000, move)


move()

ws.mainloop()
Now the window doesn't grow each time a new image is displayed. If there was just a way to get rid of those horrible global variables. Oh! I know! I will make a class to keep all the info needed for the slideshow.
import tkinter as tk
import itertools

images = ["dice1.png", "dice2.png", "dice3.png", "dice4.png", "dice5.png", "dice6.png"]


class ImageViewer(tk.Tk):
    """A tkinter window that displays images like a slideshow"""
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)
        # Label to display the image
        self.image_label = tk.Label(self)
        self.image_label.pack()
        # Label to display the image file name
        self.name_label = tk.Label(self, width=30)
        self.name_label.pack()
        self.image = None
        self.delay = 2000
        self.running = False

    def start(self, image_files, loop=True, delay=None):
        """
        Start slide show.  Set loop to True to cycle through images forever.
        Set delay to seconds that image is shown.
        """
        if loop:
            """Cycle forever"""
            self.image_files = itertools.cycle(image_files)
        else:
            """Show slides once"""
            self.image_files = iter(image_files)
        if delay is not None:
            self.delay = delay * 1000
        self.running = True
        self.update_image()

    def stop(self):
        """Stop slideshow"""
        self.running = False

    def update_image(self):
        """Show the next image"""
        if self.running:
            try:
                image_file = next(self.image_files)
                self.name_label["text"] = image_file
                self.image = tk.PhotoImage(file=image_file)
                self.image_label["image"] = self.image
                self.after(self.delay, self.update_image)
            except StopIteration:
                self.running = False


viewer = ImageViewer()
viewer.start(images, loop=True, delay=1)

viewer.mainloop()
Gribouillis and Frankduc like this post
Reply
#5
Hi dean,

Yes i research this before asking and have found an answer on stackoverflow but i didn't understand the solution.

As usual this is a great explanation on how to do things with classes.
This is what i am suppose to reproduce. https://www.youtube.com/watch?v=oNA4fiQRQhw
But i must add buttons with the Ras Pi to pause the images and to switch images during time display.
They must be displayed from 8:30 morning to 8:30 pm.

Was wondering if it is possible to replace loop = True in start() function by datetime.now(hour = 8:30)
I have seen some way to do that with DT.datetime.combine(DT.date.today(), DT.time(hour= 8))

and simply add an elif statement to switch to another set of images.


I did a quick test no error but no images:

import tkinter as tk
import datetime as DT
import time
 
image_files = [
    '/home/pi/Desktop/jpg2png/athenaR.png',
'/home/pi/Desktop/jpg2png/EosR.png',
'/home/pi/Desktop/jpg2png/k.png',
'/home/pi/Desktop/jpg2png1/athena1.png',
'/home/pi/Desktop/jpg2png1/meteor.png',
'/home/pi/Desktop/jpg2png1/tshenandoah.png',
'/home/pi/Desktop/jpg2png1/Wolfhound.png',
'/home/pi/Desktop/jpg2png1/Aunderway.png'
]

image_files1 = [
    '/home/pi/Desktop/jpg2png2/A.png',
'/home/pi/Desktop/jpg2png2/antibe.png',
'/home/pi/Desktop/jpg2png2/dubai.png',
'/home/pi/Desktop/jpg2png2/KHALILAH.png',
'/home/pi/Desktop/jpg2png2/luxury-yatch.png',
'/home/pi/Desktop/jpg2png2/turquoise.png',
]
ws = tk.Tk()
image_label = tk.Label(ws, font="bold")
image_label.pack()
index = 0
 
 
def move():
    global index
    global img
    img = tk.PhotoImage(file=image_files[index])
    image_label["image"] = img
    index = (index + 1) % len(image_files)
    ws.after(2000, move)
 
def move1():
    global index
    global img
    img = tk.PhotoImage(file=image_files1[index])
    image_label["image"] = img
    index = (index + 1) % len(image_files1)
    ws.after(2000, move)
 


def time_shift():

    target = DT.datetime.combine(DT.date.today(), DT.time(hour=8))
    
def time_shift2():

    target = DT.datetime.combine(DT.date.today(), DT.time(hour=10))

if time_shift():
    move()
elif time_shift2():
    move1()
    


time_shift()
 
ws.mainloop()
Thank you for your input.
Reply
#6
time_shift() and time_shift2() do nothing and return None, so the branches of the if are never executed.

That said, use classes.
Reply
#7
Hi Gribouillis,

I manage to make it work but images dont switch. Is hour = 10 am in the morning or 10 pm?
I am not great with classes but i will try.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  Tkinter Pillow Resize Image Looks Choppy While Resizing AaronCatolico1 2 1,326 Jan-03-2023, 05:41 PM
Last Post: AaronCatolico1
  rotating an array djwilson0495 3 2,008 Jan-08-2021, 01:18 AM
Last Post: Skaperen
  rotating and resizing objects jenya56 3 2,322 Jul-26-2019, 12:06 AM
Last Post: scidam

Forum Jump:

User Panel Messages

Announcements
Announcement #1 8/1/2020
Announcement #2 8/2/2020
Announcement #3 8/6/2020