Python Forum
Updating/running code when path changes
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Updating/running code when path changes
#11
(Jul-08-2022, 08:43 PM)deanhystad Wrote: The most likely error is it failed to open an image to display. I didn't test any of my code, and I could have introduced an error when I modified your source.

When I run print(filename) in the code it prints out the correct path to the image, could it be how the image is being rendered? I tested another set of images and jpg images but no luck.
Reply
#12
Write a small program that opens a file and displays an image. Don't worry about the .after() or getting the filename from somewhere. Just open a file in the same folder as the python program. If you can get that to work, modify so it opens a file in a different folder. If you can get that working then you should know enough to fix your problem.
Reply
#13
(Jul-08-2022, 09:22 PM)deanhystad Wrote: Write a small program that opens a file and displays an image. Don't worry about the .after() or getting the filename from somewhere. Just open a file in the same folder as the python program. If you can get that to work, modify so it opens a file in a different folder. If you can get that working then you should know enough to fix your problem.

I get the image to work and open in a window with this code:

from tkinter import *
root = Tk()
canvas = Canvas(root, width = 300, height = 300)
canvas.pack()
img = PhotoImage(file="/Users/hermann/Dropbox/electronics/moon/test/near_side_1024x1024x8/180.png")      
canvas.create_image(20,20, anchor=NW, image=img)
mainloop()
But I'm not sure what I can use from this code and insert in the other code. I've been trying all kinds of combinations but I really don't know what I'm doing.
This code will place the hard coded image path in the middle of the black screen.

import json
import tkinter
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np

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

path = "/Users/hermann/Dropbox/electronics/moon/test/near_side_1024x1024x8/"

def update_phase():
    """Retrieve moon phase and update image"""
    with open("number.json", "r") as f:
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["text"])
    # Open file and update image
    showPIL(path + op + ".png")

    # Run myself again after an hour (3,600,000 milliseconds)
    root.after(3600, update_phase)

def showPIL(filename):
    """Open image file and draw image on canvas"""
    pilImage = Image.open(filename)
    imgWidth, imgHeight = pilImage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w / imgWidth, h / imgHeight)
        imgWidth = int(imgWidth * ratio)
        imgHeight = int(imgHeight * ratio)
        pilImage = pilImage.resize((imgWidth, imgHeight), Image.ANTIALIAS)
    #image = ImageTk.PhotoImage(pilImage)


    #canvas.create_image(20,20, anchor=NW, image=img)
    print(filename)

root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
canvas = tkinter.Canvas(root, width=w, height=h)


img = PhotoImage(file="/Users/hermann/Dropbox/electronics/moon/test/near_side_1024x1024x8/180.png")
canvas.create_image(w / 2, h / 2, image=img)
canvas.pack()
canvas.configure(background="black")

update_phase()  # Starts the update loop
root.mainloop()
But When I replace the path with filename, I get:

Error:
Hermanns-iMac:test hermann$ python3 test2.py Traceback (most recent call last): File "/Users/hermann/Dropbox/electronics/moon/test/test2.py", line 49, in <module> img = PhotoImage(filename) NameError: name 'filename' is not defined
If I move this code to the def showPIL(filename):, I'm back at the black screen.

img = PhotoImage(file="/Users/hermann/Dropbox/electronics/moon/test/near_side_1024x1024x8/180.png")
canvas.create_image(w / 2, h / 2, image=img)

Anyone? Please Angel
I got this to work now. All I had to do was add in global pilImage and global image in def showPIL(filename): and uncomment the imagesprite line.

Thanks to everyone who helped.

Here's the working code:
import json
import tkinter
import tkinter as tk
from PIL import Image, ImageTk
import numpy as np
 
from tkinter import *
from PIL import ImageTk, Image
import os

path = "/users/hermann/Dropbox/electronics/moon/project/project/near_side_1024x1024x8/" #Path to images folder

def update_phase():
    """Retrieve moon phase and update image"""
    with open("number.json", "r") as f: #number.json created by Scrapy scraper
        distros_dict = json.load(f)
    for distro in distros_dict:
        op = json.dumps(distro["value"])
    # Open file and update image
    showPIL(path + op + ".png") #op is the value from the number.json file

    # Run myself again
    root.after(60000, update_phase) #Updates every 1 min

def showPIL(filename):
    global pilImage
    global image
    """Open image file and draw image on canvas"""
    pilImage = Image.open(filename.replace( '"', '')) #Removes "" from path
    imgWidth, imgHeight = pilImage.size
    if imgWidth > w or imgHeight > h:
        ratio = min(w / imgWidth, h / imgHeight)
        imgWidth = int(imgWidth * ratio)
        imgHeight = int(imgHeight * ratio)
    pilImage = pilImage.resize((1024, 1024), Image.ANTIALIAS)
    image = ImageTk.PhotoImage(pilImage)
    imagesprite = canvas.create_image(w / 2, h / 2, image=image)
    #print(filename) #Uncomment to test if path is correct

root = tkinter.Tk()
w, h = root.winfo_screenwidth(), root.winfo_screenheight()
root.overrideredirect(1)
root.geometry("%dx%d+0+0" % (w, h))
root.focus_set()
root.bind("<Escape>", lambda e: (e.widget.withdraw(), e.widget.quit()))
canvas = tkinter.Canvas(root, width=w, height=h)
canvas.pack()
canvas.configure(background="black", highlightthickness=0)

update_phase()  # Starts the update loop
root.mainloop()
Reply
#14
pilImage does not need to be global, it is only used to create image. After image is created, pilImage can be discarded.

Tk does not keep reference images passed as arguments. I know this is a problem with buttons and labels, I guess I should not be surprised it is a problem with canvas. The problem is that the only variable referencing the image logic is local to showPIL. When showPIL exits the local variables are deleted. Now nobody has a reference to the image object. There is no way to use it so Python deletes it.

Making a global variable just to keep a reference to an image is ugly. Global variables should only be used when the represent something that is really global (used in multiple scopes inside the module). Instead of making a global variable I would make "image" an attribute of the canvas that holds the image.
    canvas.image = ImageTk.PhotoImage(pilImage)
    canvas.create_image(w / 2, h / 2, image=canvas.image)
Reply
#15
You didn't keep a reference to image, so it is garbage collected when the function exits. You can append to a list or create an instance object that survives, like canvas

    canvas.image = ImageTk.PhotoImage(pilImage)
    imagesprite = canvas.create_image(w / 2, h / 2, image=canvas.image) 
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  running the code and seeing the GUI chriswrcg 1 817 May-19-2023, 04:49 PM
Last Post: deanhystad
  [PyQt] source code is not running in REDHAT 7 linux platform shridhara 0 2,123 May-23-2018, 07:58 AM
Last Post: shridhara
  Errors while running dash plotly code Nischitha 3 5,250 Aug-24-2017, 10:54 AM
Last Post: Larz60+

Forum Jump:

User Panel Messages

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