0

I've seen almost every post about this issue and nothing solved it. At this point I'm not getting an error, it's just not working at all.

So, I'm just making a silly program with TKinter to simulate the DVD bouncing logo, which works, but doesn't change the colors (in this case I have 4 different images that I try to change, but are not changing)

import random
from tkinter import *
from PIL import ImageTk, Image

root = Tk()
root.title("DVD Logo")
root.resizable(False, False)
root.attributes("-fullscreen", True)

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

dvd_vermelho = Image.open("dvd_vermelho.png").resize((256, 256))
dvd_verde = Image.open("dvd_verde.png").resize((256, 256))
dvd_azul = Image.open("dvd_azul.png").resize((256, 256))
dvd_amarelo = Image.open("dvd_amarelo.png").resize((256, 256))

x,y = dvd_vermelho.size
canvas_x = width
canvas_y = height

canvas = Canvas(root, width=canvas_x, height=canvas_y, bg="blue")
canvas.pack()
root.update()
canvas_widht = canvas.winfo_width()
canvas_height = canvas.winfo_height()

dvd_vermelho_tk = ImageTk.PhotoImage(dvd_vermelho, master=canvas)
dvd_verde_tk = ImageTk.PhotoImage(dvd_verde, master=canvas)
dvd_amarelo_tk = ImageTk.PhotoImage(dvd_amarelo, master=canvas)
dvd_azul_tk = ImageTk.PhotoImage(dvd_azul, master=canvas)

dvd_logos = [dvd_amarelo_tk, dvd_verde_tk, dvd_vermelho_tk, dvd_azul_tk]
containerDVD = canvas.create_image(0, 0, anchor=NW, image=dvd_logos[0])

valuex = 2
valuey = 3

random_x = random.randint(0, canvas_widht - x)
random_y = random.randint(0, canvas_height - y)

canvas.move(containerDVD, random_x, random_y)

initial_trajectory_x = random.choice([-valuex, valuex])
initial_trajectory_y = random.choice([-valuey, valuey])

current_posx = random_x
current_posy = random_y

def changeImage():
    global dvd_azul_tk, dvd_verde_tk, dvd_vermelho_tk, dvd_amarelo_tk, containerDVD
    last_exit = dvd_logos.pop(0)
    dvd_logos.append(last_exit)
    canvas.delete(containerDVD)
    containerDVD = canvas.create_image(current_posx, current_posy, anchor=NW, image=dvd_logos[0])

def moveDVD():
    global current_posx, current_posy, initial_trajectory_x, initial_trajectory_y, dvd

    canvas.move(containerDVD, initial_trajectory_x, initial_trajectory_y)
    current_posx += initial_trajectory_x
    current_posy += initial_trajectory_y

    if current_posx <= 0 or current_posx+x >= canvas_widht:
        initial_trajectory_x *= -1
        changeImage()
    if current_posy <= 0 or current_posy+y >= canvas_height:
        initial_trajectory_y *= -1
        changeImage()

    root.after(12, moveDVD)

root.after(12, moveDVD)

root.mainloop()

The real issue is in this line of code:

def changeImage():
    global dvd_azul_tk, dvd_verde_tk, dvd_vermelho_tk, dvd_amarelo_tk, containerDVD
    last_exit = dvd_logos.pop(0)
    dvd_logos.append(last_exit)
    canvas.delete(containerDVD)
    containerDVD = canvas.create_image(current_posx, current_posy, anchor=NW, image=dvd_logos[0])

Here I try to delete the previous image and create another one. I've already tried canvas.itemconfig(containerDVD, image=dvd_logos[0]) too but it doesn't work either. Also tried updating, but didn't work.

Is there any steps I'm missing? Is this about the image reference? Or is it about my after loop?

Guides I've seen to help solving the problem: Tkinter canvas fails to update image - https://www.tutorialspoint.com/how-to-update-an-image-in-a-tkinter-canvas 'image "pyimage2" doesn't exist'? (this error happend before I transformed everything in PhotoImage) Why does Tkinter image not show up if created in a function? - Python Tkinter ~ canvas.delete()

  • What have you done to debug this? Have you verified that `current_posx`, `current_posy`, `x`, and `y` are both the value and type that you assume they are? Are you certain that `dvd_logos[0]` contains an image? Have you verified that `canvas_widht` and `canvas_height` are what you assume they are? I'm guessing one or more of your assumptions are incorrect. – Bryan Oakley Jun 26 '23 at 02:42
  • @BryanOakley so `current_posx` and `current_posy` are just to get track of the image on my screen and add the static value to it so it can move smoothly through the screen, for the debug I've just printed the value, which seem to be right in the position of my screen resolution. `x` and `y` are just the image sizes, I've done it in case I want to change the size later, but all works fine. Now `dvd_logos[0]` returns me **pyimage1 to pygame4**, is it ok? Finally, `canvas_widht` and `canvas_height` work fine too, in this case is just my screen resolution since it's fullscreen. – Gustavo Godoy Jun 26 '23 at 12:32
  • This code works fine for me. You say you want the image to change colors, but I don't see any code that tries to change the color of the images or the background. It does cycle through the four images, however. – Bryan Oakley Jun 26 '23 at 14:50
  • Yes, there is no code to change the color. The problem is: the images are cycling, but they are not changing. The code starts with the red version of the logo, when it touches the wall the function `changeImage()` is called, but the image still the red version, it doesn't change (it's not displayed) for the others inside `dvd_logos`, even thought it's changing in the list. But now that you mentioned, maybe I'll just try to get a white image and just make a code to change the color. – Gustavo Godoy Jun 26 '23 at 17:49
  • The images cycle just fine for me. – Bryan Oakley Jun 26 '23 at 22:55
  • You have used the same image file "dvd_vermelho.png" for the four images. – acw1668 Jun 27 '23 at 00:44
  • @acw1668 yeah, I realized that, but even when I change the images still wouldn't change. Strange, but thanks, I solved it. – Gustavo Godoy Jun 28 '23 at 17:51

2 Answers2

0

I don't know the exact intent, but the code seems to work fine.

def changeImage():
    global dvd_azul_tk, dvd_verde_tk, dvd_vermelho_tk, dvd_amarelo_tk, containerDVD
    last_exit = dvd_logos.pop(0)
    dvd_logos.append(last_exit)
    canvas.itemconfig(containerDVD, image=dvd_logos[0])

Could it be because of a typo in the question?

canvas.itemconfig(containterDVD, image=dvd_logos[0])
canvas.itemconfig(containerDVD, image=dvd_logos[0])
kimhyunju
  • 309
  • 1
  • 7
0
import random
from tkinter import *
from PIL import ImageTk, Image

root = Tk()
root.title("DVD")
root.resizable(False, False)
root.attributes("-fullscreen", True)

width = root.winfo_screenwidth()
height = root.winfo_screenheight()

dvd_colors = [(9, 0, 137, 255), (0, 255, 0, 255), (255, 0, 0, 255), (255, 255, 0, 255)]
dvd_images = []

dvd = Image.open("dvd.png").resize((324, 256))
x,y = dvd.size

canvas_x = width
canvas_y = height

canvas = Canvas(root, width=canvas_x, height=canvas_y, bg='#0044FF')
canvas.pack()
root.update()
canvas_widht = canvas.winfo_width()
canvas_height = canvas.winfo_height()

i = 0
for c in range(0, len(dvd_colors)):
    dvd = Image.open("dvd.png").resize((x, y)).convert("RGBA")
    dvd_pixels = dvd.getdata()
    new_dvd = []

    for pixel in dvd_pixels:
        if pixel == (255,255,255,255):
            new_dvd.append(dvd_colors[i])
        else:
            new_dvd.append(pixel)

    dvd.putdata(new_dvd)
    dvd_images.append(ImageTk.PhotoImage(dvd, master=canvas))
    i += 1

containerDVD = canvas.create_image(0, 0, anchor=NW, image=dvd_images[0])

valuex = 2
valuey = 3

random_x = random.randint(0, canvas_widht - x)
random_y = random.randint(0, canvas_height - y)

canvas.move(containerDVD, random_x, random_y)

initial_trajectory_x = random.choice([-valuex, valuex])
initial_trajectory_y = random.choice([-valuey, valuey])

current_posx = random_x
current_posy = random_y

def changeColor():
    last_dvd = dvd_images.pop(0)
    dvd_images.append(last_dvd)
    canvas.itemconfigure(containerDVD, image=dvd_images[0])

def moveDVD():
    global current_posx, current_posy, initial_trajectory_x, initial_trajectory_y

    canvas.move(containerDVD, initial_trajectory_x, initial_trajectory_y)
    current_posx += initial_trajectory_x
    current_posy += initial_trajectory_y

    if current_posx <= 0 or current_posx+x >= canvas_widht:
        initial_trajectory_x *= -1
        changeColor()
    if current_posy <= 0 or current_posy+y >= canvas_height:
        initial_trajectory_y *= -1
        changeColor()

    root.after(12, moveDVD)

root.after(12, moveDVD)

root.mainloop()

So, I'm not entirely sure of what I did, but it solved the problem. Now I have only one image that goes through a loop to create all the colors I want for the image. Then, I send a PhotoImage to a list, which is very similar to what I had before, but I was manually inserting my PhotoImages in the list.

My guess is, it has something to do with the PhotoImage reference and his garbage collector.

Also, used itemconfigure, which I also tried in my previous code, but didn't work.

If anyone sees something that explains why it's working now, I'd appreciate a lot. Also, thanks for the ones that helped.