strange behavior of tkinter with pil image [duplicate] - python-3.x

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 simply want to show an image in a label widget. I managed the task by the following code:
import tkinter as tk
from PIL import Image,ImageTk
import requests
root=tk.Tk()
url="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/500px-SNice.svg.png"
imageurl=requests.get(url, stream=True)
image=Image.open(imageurl.raw)
img = ImageTk.PhotoImage(image.resize(size=(500,500)))
origPictureBox = tk.Label(root, image=img, anchor=tk.NW, height=500, width=500)
origPictureBox.config(image=img)
origPictureBox.pack(side=tk.TOP)
root.mainloop()
However, when I put the main tasks into a function, the picture is not displayed:
import tkinter as tk
from PIL import Image,ImageTk
import requests
def initUI(root):
url="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/500px-SNice.svg.png"
imageurl=requests.get(url, stream=True)
image=Image.open(imageurl.raw)
img = ImageTk.PhotoImage(image.resize(size=(500,500)))
origPictureBox = tk.Label(root, image=img, anchor=tk.NW, height=500, width=500)
origPictureBox.config(image=img)
origPictureBox.pack(side=tk.TOP)
root=tk.Tk()
initUI(root)
root.mainloop()
Can somebody explain this behavior? If other items are to be displayed (buttons, etc.), they are visible, it's just the image that hides.
The same happens if I use a class instead of the function initUI.
It's my first question in stackOverflow and I am sorry, if the answer is obvious.

You need to keep reference to the image, or its get garbage collected
So add:
l = tk.Label(root)
l.image = img
Full code
import tkinter as tk
from PIL import Image,ImageTk
import requests
def initUI(root):
url="https://upload.wikimedia.org/wikipedia/commons/thumb/e/e0/SNice.svg/500px-SNice.svg.png"
imageurl=requests.get(url, stream=True)
image=Image.open(imageurl.raw)
img = ImageTk.PhotoImage(image.resize(size=(500,500)))
l = tk.Label(root)
l.image = img
origPictureBox = tk.Label(root, image=img, anchor=tk.NW, height=500, width=500)
origPictureBox.config(image=img)
origPictureBox.pack(side=tk.TOP)
root=tk.Tk()
initUI(root)
root.mainloop()

Related

How to embed a base64 image into python 3 guizero/tkinter?

I am trying to embed a base64 image into either a box or the picture widget so my application requires less files. I found a way to do it with plain tkinter at Base64 string to image in tkinter answered by Bryan Oakley and I updated the code to work with python 3.
What they did
import tkinter as tk
IMAGE_DATA = '''
R0lGODlhEAAQALMAAAAAAP//AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA\nAAAAACH5BAEAAAIALAAAAAAQABAAQAQ3UMgpAKC4hm13uJnWgR
TgceZJllw4pd2Xpagq0WfeYrD7\n2i5Yb+aJyVhFHAmnazE/z4tlSq0KIgA7\n
'''
root = tk.Tk()
image = tk.PhotoImage(data=IMAGE_DATA)
label = tk.Label(root, image=image, padx=20, pady=20)
label.pack()
root.mainloop()
What I've tried
import tkinter as tk
from guizero import *
import base64
app= App()
#the same image they used for testing
IMAGE_DATA = '''
R0lGODlhEAAQALMAAAAAAP//AP///wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
AAAAAAAAAAAA\nAAAAACH5BAEAAAIALAAAAAAQABAAQAQ3UMgpAKC4hm13uJnWgR
TgceZJllw4pd2Xpagq0WfeYrD7\n2i5Yb+aJyVhFHAmnazE/z4tlSq0KIgA7\n
'''
box=Box(app,width=app.width,height=app.height)
box.bg='gray'
#button=PushButton(app, image=IMAGE_DATA)
#image = Picture(box, image=IMAGE_DATA)
#picText = Text(box, tk.data=IMAGE_DATA)
#Pure tkinter
'''
image = tk.PhotoImage(data=IMAGE_DATA)
label = tk.Label(box, image=image, padx=20, pady=20)
label.pack()
'''
app.display()
What I used
https://lawsie.github.io/guizero/ (module)
https://base64.guru/converter/encode/image (converts images to base 64)
The image option requires an instance of the PhotoImage class from tkinter. So, create an instance, and pass that to guizero widget.
image = tk.PhotoImage(data=IMAGE_DATA)
button=PushButton(app, image=image)

unable to apply a ttk theme to .toplevel()

I'm trying to rcreate a slasph screen which doubles as an about screen on a menu bar in tkinter and python 3.
so far I've read I should be using a Toplevel() method on the second splash_root but It justs send me the error that, name 'Toplevel' is not defined.
Have I missed something basic here or just misunderstood how Toplevel() works?
import tkinter as tk
import tkinter.ttk as ttk
from PIL import ImageTk, Image
from ttkthemes import ThemedTk
def splash_screen():
splash_root = Toplevel(root)
splash_root.geometry("500x400")
img_title = ImageTk.PhotoImage(Image.open("art/icons/random.png"))
lbl_img_title = ttk.Label(splash_root,image=img_title)
lbl_img_title.pack(side="top",pady=20)
splash_label_by = ttk.Label(splash_root, text="name")
splash_button = ttk.Button(splash_root, text="close", command=lambda: splash_root.destroy())
splash_label_by.pack(pady=20, padx=20)
splash_button.pack(ipadx=10, ipady=10)
splash_screen()
root = ThemedTk(themebg=True)
root.set_theme('black')
root.title("splash")
root.geometry("500x500")
root.mainloop()
The answer to your question:
#Toplevel(root) is not defined
tk.Toplevel(root) #will solve your Toplevel problem.
If you call
splash_screen()
before declaring root, root will be not defined and your code still wont work.

Treeview Image not displaying

having problems displaying an image using treeview. Found some other mentions on the net with a similar problem but the answers do not seem to work for me. I am using Win10 if that makes a difference
import ttkthemes
import tkinter as tk
from tkinter import ttk
from tkinter.messagebox import showinfo
from tkinter import PhotoImage
from PIL import Image, ImageTk
self = tk.Tk()
self.title('Tkinter PhotoImage Demo')
#self.image = Image.open("A4.bmp")
#self.python_image = ImageTk.PhotoImage(self.image)
#print(self.python_image)
#ttk.Label(self, image=self.python_image).pack()
# columns
columns = ('#1', '#2')
tree = ttk.Treeview(self, columns=columns, show='headings', height=20)
tree.tag_configure('oddrow', background='#ece0cf')
tree.tag_configure('evenrow', background='#e0e0e0')
style = ttk.Style()
style.theme_use('clam')
style.configure("Treeview",font=(None,12))
style.configure("Treeview.Heading", font=(None, 12))
# define headings
tree.heading('#1', text='Date')
tree.column("#1", minwidth=0, width=160)
tree.heading('#2', text='Logo')
tree.column("#2", minwidth=0, width=80)
# add a scrollbar
scrollbar = ttk.Scrollbar(self, orient=tk.VERTICAL, command=tree.yview)
tree.configure(yscroll=scrollbar.set)
scrollbar.grid(row=0, column=1, sticky='ns')
tree.grid(row=0, column=0, sticky='nsew')
logo="A4.bmp"
rowcol='oddrow'
im = Image.open(logo)
ph = ImageTk.PhotoImage(im)
print(ph)
tree.insert('', -1, values=("2021-03-25", logo), image=ph, tags=(rowcol,))
tree.grid(row=0, column=0, sticky='nsew')
self.update_idletasks()
self.update()
If it helps the value of ph is: pyimage1
The commented out code at the start displays the image just fine, so the issue seems to be on adding the image itself into the tree.insert.... bit of coding
Whilst I have your attention and as related but very minor questions, is there also a way to add a second image into treeview? Plus is there a way to display some values, then an image, then some more values, then another image and finally more values, or do the images have to be at the start or end of the rows?

Display video size on label tkinter

The below code displays video on the label. But, problem is that, it is displayed in a very zoom (large) manner. I want to resize it to display correctly on label. When I use the option image=image.resize(), I get an error
ValueError: cannot resize this array: it does not own its data
import tkinter as tk, threading
import imageio
from PIL import Image, ImageTk
video_name = "e.mp4"
video = imageio.get_reader(video_name)
#video = video.resize(20,20)
def stream(label):
for image in video.iter_data():
frame_image = ImageTk.PhotoImage(Image.fromarray(image))
label.config(image=frame_image)
label.image = frame_image
root = tk.Tk()
my_label = tk.Label(root, width=500,height=500)
my_label.place(x=0,y=0)
thread = threading.Thread(target=stream, args=(my_label,))
thread.daemon = 1
thread.start()
root.mainloop()
You can call resize() on the return image of Image.fromarray(image):
frame_image = ImageTk.PhotoImage(Image.fromarray(image).resize((100,100)))

Trouble adding Images into a Gui using tkinter

OK so i am trying to make a program that displays an image when pressing a button, and i am having trouble getting the images into the program
this is my full code:
# Nicolas Bart
import tkinter as tk
from PIL import Image, ImageTk
from tkinter import *
window = tk.Tk()
window.title('Bad Meme Generator')
window.geometry('500x500')
window.configure(bg='saddle brown')
meme_label = tk.Label(window, text='PRESS BUTTON FOR BAD MEMES:',
fg='blue4', bg='brown4', font=('comicsans', '20'))
meme_label.grid(pady=25, padx=25, column=0, row=0)
def button_command():
meme_window = tk.Tk()
meme_window.title('I Warned You')
meme_window.grid()
image = Image.open('pexels-photo-247932.jpg')
photo = ImageTk.PhotoImage(image)
label = tk.Label(meme_window, image=photo)
label.image = photo
label.place(x = 0, y = 0)
button = tk.Button(window, text='Dont Do It!', command=button_command,
padx=100, pady=75, font=('comicsans', '20'),
bg='brown4', fg='blue4')
button.grid(column=0, row=1)
warning_label = tk.Label(window, text="Really shit tier memes incoming:",
bg='brown4', fg='blue4',
font=('comicsans', '20'))
warning_label.grid(pady=75)
window.mainloop()
every time i run this program, when i press the button to open the image, it gives the error "AttributeError: type object 'Image' has no attribute 'open'"
the specific part of the program that is giving the error is:
def button_command():
meme_window = tk.Tk()
meme_window.title('I Warned You')
meme_window.grid()
image = Image.open('pexels-photo-247932.jpg')
photo = ImageTk.PhotoImage(image)
label = tk.Label(meme_window, image=photo)
label.image = photo
label.place(x = 0, y = 0)
any help would be appreciated. Thank you :)
This is a good example of why you shouldn't do from tkinter import *. Tkinter has an Image class, so by doing this import after importing Image from PIL you overwrite the PIL class with the tkinter class.
Since you're already importing tkinter the preferred way (import tkinter as tk), you don't need to import tkinter a second time. You need to remove the statement from tkinter import *.
You also make the mistake of creating more than one instance of Tk. I don't know if it contributes to the problem or not, but it's not something you should be doing. If you need additional windows then you should create instances of Toplevel.

Resources