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()
4
  • You need to save the image reference outside of your function or else it will just disappear after the function completes. Commented Apr 26, 2019 at 19:54
  • @Mike-SMT Can you specify which variable exactly is a reference? Commented Apr 26, 2019 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. Commented Apr 26, 2019 at 19:58
  • I feel like I probably close a duplicate like this at least 2-3 times a week. Commented Apr 26, 2019 at 20:11

1 Answer 1

2

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()
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.