0

First of all, my code is based on this StackOverflow answer.

Due to circumstance, I am trying to have most of the code packed into a function that I call ImgFromUrl()

import io
import tkinter as tk
import urllib.request
from PIL import Image, ImageTk

def ImgFromUrl(root, url):
    with urllib.request.urlopen(url) as connection:
        raw_data = connection.read()
    im = Image.open(io.BytesIO(raw_data))
    image = ImageTk.PhotoImage(im)
    return tk.Label(root, image=image)

root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"

widget = ImgFromUrl(root,url)
widget.grid(row=0,column=0)

root.mainloop()

And for some reason, the image does not show up (though the Tkinter window was automatically resized to the size of the image).

However, this works:

# same imports

root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"

with urllib.request.urlopen(url) as connection:
    raw_data = connection.read()
im = Image.open(io.BytesIO(raw_data))
image = ImageTk.PhotoImage(im)

widget = tk.Label(root, image=image)
widget.grid(row=0,column=0)

root.mainloop()
Programer Beginner
  • 1,377
  • 6
  • 21
  • 47
  • You need to save the image reference outside of your function or else it will just disappear after the function completes. – Mike - SMT Apr 26 '19 at 19:54
  • @Mike-SMT Can you specify which variable exactly is a reference? – Programer Beginner Apr 26 '19 at 19:56
  • `image = ImageTk.PhotoImage(im)` is deleted as soon as the function ends so you need to have that saved as a global variable instead. That said why are you creating your widget like this? It seams overly complicated. – Mike - SMT Apr 26 '19 at 19:58
  • I feel like I probably close a duplicate like this at least 2-3 times a week. – Bryan Oakley Apr 26 '19 at 20:11

1 Answers1

1

So your issue is because image is deleted as soon as the function end and tkinter needs the image to be saved for a reference somewhere.

We can do this with global or by returning the image to a variable defined in the global.

Option 1 global:

import tkinter as tk
import urllib.request
from PIL import Image, ImageTk
import io


def ImgFromUrl(url):
    global image
    with urllib.request.urlopen(url) as connection:
        raw_data = connection.read()
    im = Image.open(io.BytesIO(raw_data))
    image = ImageTk.PhotoImage(im)
    return image

root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"
widget = tk.Label(root, image=ImgFromUrl(url))
widget.grid(row=0, column=0)

root.mainloop()

Option 2 returning the image object to a variable defined in the global namespace:

import tkinter as tk
import urllib.request
from PIL import Image, ImageTk
import io


def ImgFromUrl(url):
    with urllib.request.urlopen(url) as connection:
        raw_data = connection.read()
    im = Image.open(io.BytesIO(raw_data))
    image = ImageTk.PhotoImage(im)
    return image

root = tk.Tk()
url = "http://imgs.xkcd.com/comics/python.png"
image = ImgFromUrl(url)
widget = tk.Label(root, image=image)
widget.grid(row=0, column=0)

root.mainloop()
Mike - SMT
  • 14,784
  • 4
  • 35
  • 79