Python Forum
Putting code into a function breaks its functionality, though the code is identical!
Thread Rating:
  • 0 Vote(s) - 0 Average
  • 1
  • 2
  • 3
  • 4
  • 5
Putting code into a function breaks its functionality, though the code is identical!
#1
Hello, I am perplexed by this problem. I have a chunk of code which appears to work in the body of my Python script, but once I stick the same code into a function, bam! Failure! I will describe the problem briefly with the relevant code portion, then provide the full NON-working code below. I am also attaching two screen shots: the first:

https://www.dropbox.com/s/icftyu0kq9qzde...g.png?dl=0

shows the code being executed in the script body, producing an image. The second image:

https://www.dropbox.com/s/iwpy9j8sx7ucmk...n.png?dl=0

shows the code being executed in a function, which appears to flash an image on the GUI for a split second before going white (and no buttons).

Brief description of the goal: a label named "image_layer" is to have its image changed to a new random image from an array of image names "file_list" upon press of the button "button_newpicture".

Problem: Ideally, there is a function (say, called ChangeImage()) which re-assigns the "image_layer" image attribute upon the press of a button "button_newpicture" (say, from Image_524.jpg to Image_823.jpg). I drew up the following code, which upon an initial run of the program produces an image. But the code is just sitting in the script body:

#create random index in the range of entries 0-840 
index = random.randint(0, 840)
#create a string to the new image referenced by the random index in the file_list array of image names
imgstring = "Images/" + str(file_list[index])
#create a tkinter photoimage from the image string 
newimage = ImageTk.PhotoImage(Image.open(imgstring))
#Change the label [i]image[/i] attribute
image_layer.configure(image=newimage)
image_layer.update()   
NOW, When I put that exact code into my hypothetical function ChangeImage() (and add a call for call ChangeImage() after its definition), it looks like the following (note, the function instructions are properly indented although they do not show up that way in the published version of this post):

def ChangeImage():
    index = random.randint(0, 840)
    imgstring = "Images/" + str(file_list[index])
    newimage = ImageTk.PhotoImage(Image.open(imgstring))
    image_layer.configure(image=newimage)
    image_layer.update()
    

ChangeImage()
Now, it produces an image on my GUI for a split second and then the whole window goes white. Can anyone help me? Ideally I can get ChangeImage() working so I can call it from the button command attribute. Full code is below (the version with the non-working function, not the version hanging out in script, which is at the end of the code):

import tkinter as tk
import tkinter.font as font
import PIL
from PIL import ImageTk
from PIL import Image
import time
import os
import random

HEIGHT = 480
WIDTH = 800
file_list = os.listdir(r"Images")
file_number = len(file_list)



root = tk.Tk()
root.overrideredirect(True)  # removes title bar

canvas = tk.Canvas(root, height=HEIGHT, width=WIDTH)
canvas.pack()

frame = tk.Frame(canvas, height=HEIGHT, width=WIDTH)
frame.place(relwidth=1, relheight=1)

image_layer = tk.Label(frame)
image_layer.place(relwidth=1, relheight=1)

button_newpicture = tk.Button(image_layer, text=u"\u2764")
button_newpicture['font'] = font.Font(size=16)
button_newpicture.place(relx=0.015, rely=0.835, relwidth=0.055)

button_rotateright = tk.Button(image_layer, text=u"\u21B7", padx=3)
button_rotateright.place(relx=0.015, rely=0.93)
button_rotateleft = tk.Button(image_layer, text=u"\u21B6", padx=3)
button_rotateleft.place(relx=0.044, rely=0.93)

button_incrementright = tk.Button(image_layer, text=u"\u2190")
button_incrementright.place(relx=0.96, rely=0.93)
button_incrementleft = tk.Button(image_layer, text=u"\u2192")
button_incrementleft.place(relx=0.93, rely=0.93)

button_exit = tk.Button(image_layer, text="\u2716", command=root.quit)
button_exit.place(relx=0.965, rely=0.01)

def ChangeImage():
    index = random.randint(0, 840)
    imgstring = "Images/" + str(file_list[index])
    newimage = ImageTk.PhotoImage(Image.open(imgstring))
    image_layer.configure(image=newimage)
    image_layer.update()
    print(imgstring)

ChangeImage()
# print(imgstring)
# image_layer.configure(image=newimage)
# image_layer.image = newimage


root.mainloop()
Hopefully someone can help me! Thank you! It's my first python program!
Larz60+ write Apr-05-2021, 10:16 PM:
Please post all code, output and errors (it it's entirety) between their respective tags. Refer to BBCode help topic on how to post. Use the "Preview Post" button to make sure the code is presented as you expect before hitting the "Post Reply/Thread" button.

Fixed for you this time, please use bbcode tags on future posts.
Reply
#2
The difference is the context. Literally.

When you run the code in a function and create variables like this:
newimage = ImageTk.PhotoImage(Image.open(imgstring))
the new image is only referenced by a variable (newimage) in the FUNCTION namespace. When the function is done and cleans up after itself the function variables are tossed in the trash and garbage collected. Since there are now no references to the image, the image is also tossed in the trash for garbage collection.

When you run the same code outside a function the new image is reverenced by a variable in the GLOBAL namespace. Global variables hang around as long as the module containing them, essentially forever as far as you program is concerned. If you were to del the variable the reference count for the image would go to zero and your image would get tossed in the trash and garbage collected.

If you want to use an image in tkinter you need a variable to reference the image and the variable must be a GLOBAL variable, a CLASS variable, or an INSTANCE variable. FUNCTION variables are not good for this.
Reply


Possibly Related Threads…
Thread Author Replies Views Last Post
  I am getting an IndentError on my python code in VS Code and i dont know why jcardenas1980 11 4,380 Mar-22-2025, 09:49 AM
Last Post: Pedroski55
  Merge Python code with Micro Python code? adzy 2 974 Jul-03-2024, 11:41 AM
Last Post: kkinder
  Copying the order of another list with identical values gohanhango 7 2,615 Nov-29-2023, 09:17 PM
Last Post: Pedroski55
  Variable is not defined error when trying to use my custom function code fnafgamer239 4 1,621 Nov-23-2023, 02:53 PM
Last Post: rob101
  My code works on Jupyter Lab/Notebook, but NOT on Visual Code Editor jst 4 4,412 Nov-15-2023, 06:56 PM
Last Post: jst
  the order of running code in a decorator function akbarza 2 1,366 Nov-10-2023, 08:09 AM
Last Post: akbarza
Sad I'm stuck with the reinforcement learning function in my Code OskiLori 2 2,835 May-20-2023, 10:01 PM
Last Post: OskiLori
  Tie Breaks klatlap 6 2,414 Mar-20-2023, 12:08 PM
Last Post: klatlap
  Priority Queue with update functionality PythonNewbee 4 5,019 Dec-29-2022, 12:13 PM
Last Post: Yoriz
  python multiple try except block in my code -- can we shorten code mg24 10 15,178 Nov-10-2022, 12:48 PM
Last Post: DeaD_EyE

Forum Jump:

User Panel Messages

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