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
  Copying the order of another list with identical values gohanhango 7 1,141 Nov-29-2023, 09:17 PM
Last Post: Pedroski55
  Variable is not defined error when trying to use my custom function code fnafgamer239 4 584 Nov-23-2023, 02:53 PM
Last Post: rob101
  My code works on Jupyter Lab/Notebook, but NOT on Visual Code Editor jst 4 1,009 Nov-15-2023, 06:56 PM
Last Post: jst
  the order of running code in a decorator function akbarza 2 522 Nov-10-2023, 08:09 AM
Last Post: akbarza
Sad I'm stuck with the reinforcement learning function in my Code OskiLori 2 1,570 May-20-2023, 10:01 PM
Last Post: OskiLori
  Tie Breaks klatlap 6 1,130 Mar-20-2023, 12:08 PM
Last Post: klatlap
  Priority Queue with update functionality PythonNewbee 4 1,930 Dec-29-2022, 12:13 PM
Last Post: Yoriz
  python multiple try except block in my code -- can we shorten code mg24 10 6,138 Nov-10-2022, 12:48 PM
Last Post: DeaD_EyE
  faster code for my code kucingkembar 19 3,254 Aug-09-2022, 09:48 AM
Last Post: DPaul
  Changing a string value to a numerical value using python code and a lamda function Led_Zeppelin 6 1,609 Jul-05-2022, 11:29 PM
Last Post: deanhystad

Forum Jump:

User Panel Messages

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