Tkinter being fickle with pictures, some are blank, others are not - python

NOTE: The main problem hasn't been solved, but the code does work on a Windows PC, the problem has something to with the computer I'm using.
As the title suggests, in my code, one image works perfectly fine, yet the other doesn't display correctly.
I feel like I'm overlooking something very obvious, regardless, this is the segment of code that I'm having trouble with.
from Tkinter import *
from StringIO import StringIO
from PIL import Image,ImageTk
from urllib import urlopen
url1 = 'https://lh3.googleusercontent.com/-bnh6_0GlqbA/VUKUsl1Pp9I/AAAAAAACGoM/Vx9yu1QGIKQ/s650/Sunset.png'
url2 = 'https://lh3.googleusercontent.com/-_J57qf7Y9yI/VUPaEaMbp9I/AAAAAAACGuM/3f4551Kcd0I/s650/UpsideDawn.png'
window = Tk()
imagebytes = urlopen(url1).read()
imagedata = StringIO(imagebytes)
imagePIL = Image.open(imagedata)
imageready = ImageTk.PhotoImage(imagePIL)
imagelabel = Label(window, image = imageready)
imagelabel.image = imageready
imagelabel.pack()
window.mainloop()
If you were to run this code, you'll find that url1 will display a blank window, but url2 will display the image.

The following code works for me in Python 3, displaying either image just fine.
from tkinter import *
from PIL import Image,ImageTk
import urllib.request
import io
url1 = 'https://lh3.googleusercontent.com/-bnh6_0GlqbA/VUKUsl1Pp9I/AAAAAAACGoM/Vx9yu1QGIKQ/s650/Sunset.png'
url2 = 'https://lh3.googleusercontent.com/-_J57qf7Y9yI/VUPaEaMbp9I/AAAAAAACGuM/3f4551Kcd0I/s650/UpsideDawn.png'
window = Tk()
imagebytes = urllib.request.urlopen(url1).read()
imagedata = io.BytesIO(imagebytes)
imagePIL = Image.open(imagedata)
imageready = ImageTk.PhotoImage(imagePIL)
imagelabel = Label(window, image = imageready)
imagelabel.image = imageready
imagelabel.pack()
window.mainloop()
The following is my best guess at a Python 2 version of the above:
from Tkinter import *
from PIL import Image,ImageTk
from urllib import urlopen
import io # try this
url1 = 'https://lh3.googleusercontent.com/-bnh6_0GlqbA/VUKUsl1Pp9I/AAAAAAACGoM/Vx9yu1QGIKQ/s650/Sunset.png'
url2 = 'https://lh3.googleusercontent.com/-_J57qf7Y9yI/VUPaEaMbp9I/AAAAAAACGuM/3f4551Kcd0I/s650/UpsideDawn.png'
window = Tk()
imagebytes = urlopen(url1).read()
imagedata = io.BytesIO(imagebytes) # use bytesio instead of stringio
imagePIL = Image.open(imagedata)
imageready = ImageTk.PhotoImage(imagePIL)
imagelabel = Label(window, image = imageready)
imagelabel.image = imageready
imagelabel.pack()
window.mainloop()

Related

displaying an Image in python within a function [duplicate]

This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 2 years ago.
I'm trying to display the image from the link the code below works and shows image as intended
from tkinter import *
from PIL import ImageTk,Image
import requests
from io import BytesIO
root = Tk()
root.title('Weather')
root.iconbitmap('icon.ico')
root.geometry("450x300")
image_link = requests.get('https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0006_mist.png')
my_img = ImageTk.PhotoImage(Image.open(BytesIO(image_link.content)))
image_link =Label(root, image = my_img)
image_link.grid(row = 0, column = 0 )
root.mainloop()
but now i have to update my code a little bit and have to put this in a function
from tkinter import *
from PIL import ImageTk,Image
import requests
from io import BytesIO
root = Tk()
root.title('Weather')
root.iconbitmap('icon.ico')
root.geometry("450x300")
def image_func():
image_link = requests.get('https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0006_mist.png')
my_img = ImageTk.PhotoImage(Image.open(BytesIO(image_link.content)))
image_label =Label(root, image = my_img)
image_label.grid(row = 0, column = 0 )
image_func()
root.mainloop()
the above doesn't shows the image so I tried to to put the image label inside a frame but that just shows the frame with nothing inside also the powershell or cmd doesn't show any error
All the objects you create inside the function are local. So these object are deleted when the function exits. You need a way to keep these object existing. For example by using global variables
from tkinter import *
from PIL import ImageTk,Image
import requests
from io import BytesIO
root = Tk()
root.title('Weather')
root.iconbitmap('icon.ico')
root.geometry("450x300")
my_img = None
image_label = None
def image_func():
global my_img, image_label
image_link = requests.get('https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0006_mist.png')
my_img = ImageTk.PhotoImage(Image.open(BytesIO(image_link.content)))
image_label = Label(root, image = my_img)
image_label.grid(row = 0, column = 0 )
image_func()
root.mainloop()
Another way could be returning the objects from the function and keep the returned values
from tkinter import *
from PIL import ImageTk, Image
import requests
from io import BytesIO
root = Tk()
root.title('Weather')
root.iconbitmap('icon.ico')
root.geometry("450x300")
def image_func():
image_link = requests.get('https://assets.weatherstack.com/images/wsymbols01_png_64/wsymbol_0006_mist.png')
my_img = ImageTk.PhotoImage(Image.open(BytesIO(image_link.content)))
image_label = Label(root, image=my_img)
image_label.grid(row=0, column=0)
return my_img, image_label
my_img, image_label = image_func()
root.mainloop()

Making more windows with backgrounds (using the paths) in a for loop

I'm new to python and I'm trying this code:
import random
from random import choice
import tkinter
from tkinter import messagebox
from tkinter import *
from tkinter.filedialog import askopenfilename
import sys
from PIL import ImageTk, Image
from tkinter import filedialog
import os
num_npcs = 2
num_img_tot = 100
npc_window = {}
canvas = {}
background_label = {}
for i in range(0, num_npcs,1):
num_img = round(random.uniform(0.5, num_img_tot+0.5))
npc_window["npc_window{0}".format(i)] = Tk()
canvas["canvas{0}".format(i)] = Canvas(npc_window["npc_window{0}".format(i)], bg="blue", height=250, width=300)
filename["canvas{0}".format(i)] = PhotoImage(file=base_folder + 'biome\\'+str(char)+'\\'+str(int) + '\\'+str(num_img)+'.png')
background_label["background_label{0}".format(i)] = Label(npc_window["npc_window{0}".format(i)], image=filename["canvas{0}".format(i)])
background_label["background_label{0}".format(i)].place(x=0, y=0, relwidth=1, relheight=1)
canvas["canvas{0}".format(i)].pack()
but I probably messed up a little bit... I'm not used to GUI and stuff and I'm actually experimenting.
By the way the error is:
_tkinter.TclError: image "pyimage2" doesn't exist
I'm trying to make a program that opens X (random) images, that's why I tried Tk().
Also I'm using Pycharm in a Windows 10 machine.
The pyimage2 error may be due to an incorrect file path. Suggestion to improve folfer path:
base_folder = "base_folder"
alignment_list = [0.1, 0.2, 0.3]
integer_list = [1,2,3]
images = []
tk = Tk()
for alignment, integer in zip(alignment_list, integer_list):
image_name = "img" + str(integer) + ".png"
file_name = os.path.join(base_folder, "biome", str(alignment), str(integer), image_name)
print(file_name)
img = PhotoImage(file=file_name)
images.append(img)
Which gives
base_folder/biome/0.1/1/img1.png
base_folder/biome/0.2/2/img2.png
base_folder/biome/0.3/3/img3.png

Python 3 tkinter | Image from URL not displaying [duplicate]

This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 3 years ago.
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()
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()

why can not see images in a similar code?

please help to understand the cause of the phenomenon.
This script does not work (can not see images).
import os, sys
from tkinter import *
from PIL.ImageTk import PhotoImage
DIR_IMGS = 'imgs'
imgfiles = os.listdir(DIR_IMGS)
main = Tk()
for imgfile in imgfiles:
win = Toplevel()
imgpath = os.path.join(DIR_IMGS, imgfile)
objImg = PhotoImage(file=imgpath)
Label(win, image=objImg).pack()
main.mainloop()
and this script works (see images).
import os, sys
from tkinter import *
from PIL.ImageTk import PhotoImage
imgdir = 'images'
imgfiles = os.listdir(imgdir)
main = Tk()
savephotos = [] #?????????????????????
for imgfile in imgfiles:
imgpath = os.path.join(imgdir, imgfile)
win = Toplevel()
win.title(imgfile)
imgobj = PhotoImage(file=imgpath)
Button(win, image=imgobj).pack()
savephotos.append(imgobj) #?????????????????????
main.mainloop()
they differ only in two rows. it is unclear why such great importance "savephotos"
As FabienAndre writes in the second comment. The garbage collector deletes the image object. The image must be retained for the duration of the display.
I tried a simple code modification:
import os, sys
from tkinter import *
from PIL.ImageTk import PhotoImage
DIR_IMGS = 'imgs'
imgfiles = os.listdir(DIR_IMGS)
main = Tk()
objImgList = []
for imgfile in imgfiles:
win = Toplevel()
imgpath = os.path.join(DIR_IMGS, imgfile)
objImg = PhotoImage(file=imgpath)
Label(win, image=objImg).pack()
objImgList.append(objImg)
main.mainloop()
All pictures are now displayed.

how to display an inverted image on the screen?

please help display the inverted image on screen("main"-window).
import os, sys
import tkinter
from PIL.ImageTk import PhotoImage, Image
main = tkinter.Tk()
catalog1 = 'imgs'
catalog2 = 'newImgs'
file1 = 'n.jpg'
ima1 = os.path.join(catalog1, file1)
objImg = Image.open(ima1)
rotImg = objImg.rotate(270)
#renderImg = PhotoImage(file=ima1)
#tkinter.Label(main, image=renderImg).pack()
rotImg.save(catalog2 + '/' + 'cv.jpg')
main.mainloop()
I did it only to withdraw in an inverted image file ...
From your example, you could just reuse your label code with this renderImg
renderImg = PhotoImage(image=rotImg)
PhotoImage is an Tkinter compliant image class that you can build from either
image= PIL Image
file= file
data= raw data (usually binary image content in a string)
please try this code (updated ) :
import os, sys
import Tkinter
from PIL import ImageTk, Image
main = Tkinter.Tk()
catalog1 = 'imgs'
catalog2 = 'newImgs'
file1 = 'n.png'
ima1 = os.path.join(catalog1, file1)
img_path = "%s/%s"%(catalog1,file1);
image_ob = ImageTk.PhotoImage(Image.open(img_path).rotate(270))
Tkinter.Label(main,text="",image=image_ob).pack()
main.mainloop()

Categories