This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 4 years ago.
I am trying to display an image in a window...seems simple enough right? Well I have a big bug!
I have this exact same code in one file:
import Tkinter
root = Tkinter.Tk()
canvas = Tkinter.Canvas(root)
canvas.grid(row = 0, column = 0)
photo = Tkinter.PhotoImage(file = '/Users/Richy/Desktop/1.gif')
image1 = canvas.create_image(0,0, image=photo)
root.mainloop()
It works.
I have this in part of a bigger file:
def officialPictureWindow(self):
t = Toplevel(self)
t.wm_title("Official Image")
self.__canvas3 = Canvas(t)
self.__canvas3.grid(row = 0, column = 0)
photo = PhotoImage(file = '/Users/Richy/Desktop/1.gif')
image1 = self.__canvas3.create_image(0,0, image=photo)
It doesn't work!
That function is called when someone presses a button on a menubar I have. All the other menubar buttons I have operate properly and show their windows. There's no images in the others though.
This gives no no error. Just a blank screen. Does anyone know why?
You need to keep an additional reference to photo so it doesn't get prematurely garbage collected at the end of the function. An Introduction to Tkinter explains further:
Note: When a PhotoImage object is garbage-collected by Python (e.g. when you return from a function which stored an image in a local variable), the image is cleared even if it’s being displayed by a Tkinter widget.
To avoid this, the program must keep an extra reference to the image object. A simple way to do this is to assign the image to a widget attribute, like this:
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
In your case, you could attach the image to your self variable, or maybe the canvas. It doesn't really matter, as long as it is assigned to something.
self.image = photo
#or:
self.__canvas3.image = photo
Related
This question already has answers here:
Why does Tkinter image not show up if created in a function?
(5 answers)
Closed 7 months ago.
I am new to Python and trying to play with Tkinter and Image placement in frames.
I am wanting to create a function that will allow me to place an image into any frame. Below is the function I have created.
The code in the function works by itself (outside of a function) but does not produce the same result in the function. Outside the function it gives me the image in the frame, however in the function (unless I show the image first - commented out code) it produces a black colored frame.
I have seen that there are numerous threads similar to this problem, but none make sense to me.
# Create a function to place an image into a set frame
def PlaceImageInFrame(ImageURL, Frame, NewWidth, NewHeight, backgroundColor):
# Import the Login Logo
Login_Image = Image.open(ImageURL)
# Shrink Image
Login_Image.thumbnail((NewWidth,NewHeight))
# Show Image
#Login_Image.show()
# Bring Image into Python Tkinter
Login_Logo = ImageTk.PhotoImage(Login_Image) # PIL solution
# Create New Label in a Frame
Logo_Image = Label(Frame, image = Login_Logo, bg=backgroundColor)
# Place Label in the Frame
Logo_Image.place(x=0, y=0)
PlaceImageInFrame("Logo.jpg",Login_Logo_Frame, 400, 400, "black")
Edit 1: For example, other stack overflow posts i have seen include:
Why does Tkinter image not show up if created in a function?
[Solution] Edit 2: Found an interesting post on Github that shows the fix is as simple as reassigning the image to the label - a little strange.
https://github.com/ythy/blog/issues/302
"
photo = PhotoImage(...)
label = Label(image=photo)
label.image = photo # keep a reference!
label.pack()
"
you could not call address image as direct
first by PhotoImage class fetch this image ,then put in parameter
image=PhotoImage(file="Logo.jpg")
PlaceImageInFrame(iamge,Login_Logo_Frame, 400, 400, "black")
I have the following code:
import tkinter as tk
data = [['A',1],['B',2],['C',3],['D',4]]
def ranking():
root = tk.Tk()
root.focus_force()
windowWidth = root.winfo_reqwidth()
windowHeight = root.winfo_reqheight()
positionRight = int(root.winfo_screenwidth()/2 - windowWidth/2)
positionDown = int(root.winfo_screenheight()/2 - windowHeight/2)
root.geometry("+{}+{}".format(positionRight, positionDown))
for i in range(0,len(data)):
tk.Label(image=tk.PhotoImage(file="D:\\A\\" + data[i][0] + ".gif")).grid(row=data[i][1]-1, column=0)
root.mainloop()
ranking()
What I want to do is to have a random number of pictures (whatever is inserted in data at any moment), displayed within the window (in the order as indicated within the data), yet if I currently run the code it simply results in a blank window.The names of the pictures are literally A, B, C...and they display without a problem if I use something like (this is an extract from another piece of code I wrote):
img2 = tk.PhotoImage(file="D:\\A\\" + choice2 + ".gif")
label_img2 = tk.Label(image=img2)
label_img2.grid(row=2, column=1)
Any guidance would be very welcome as I am still quite new with working with tkinter!
When you add a PhotoImage or other Image object to a Tkinter widget, you must keep your own reference to the image object. If you don’t, the image won’t always show up.
The problem is that the Tkinter/Tk interface doesn’t handle references to Image objects properly; the Tk widget will hold a reference to the internal object, but Tkinter does not. When Python’s garbage collector discards the Tkinter object, Tkinter tells Tk to release the image. But since the image is in use by a widget, Tk doesn’t destroy it. Not completely. It just blanks the image, making it completely transparent…
The solution is to make sure to keep a reference to the Tkinter object, for example by attaching it to a widget attribute:
for i in range(0,len(data)):
photo = tk.PhotoImage(file="D:\\A\\" + data[i][0] + ".gif")
label = tk.Label(image=photo )
label.image = photo # keep a reference!
label.grid(row=data[i][1]-1, column=0)
Taken from Why do my Tkinter images not appear?
This question already has answers here:
Image resize under PhotoImage
(5 answers)
Closed 6 years ago.
I have an image that I display and I would like to resize (enlarge, actually) that image. Here's my code, using other SO questions, but I get no result - my image still has the same size. Resizing the button also does not change the image size.
I've tried the answers from this SO question: Image resize under PhotoImage but they won't work.
from Tkinter import *
root = Tk()
root.withdraw()
def cleanUp():
root.destroy()
def openWebsite():
print 'Will try to implement opening the website here.'
window = Toplevel(root)
window.protocol('WM_DELETE_WINDOW', cleanUp)
photo = PhotoImage(file="Header.pgm")
photo.zoom(2)
button = Button(window, image=photo, command=openWebsite)
button.pack()
root.mainloop()
PhotoImage.zoom() returns a new image, it does not modify the original image. Try rebinding photo like this:
photo = photo.zoom(2)
From the help:
zoom(self, x, y='') method of Tkinter.PhotoImage instance
Return a new PhotoImage with the same image as this widget
but zoom it with X and Y.
I am a begginer in python, tkinter. I have written a code that should normally display an image in a canvas.
What happens is that the main frame (gui) is displayed with the menu bar, then when I click on load image, the gui window shrinks (to 100x100 I guess) but nothing is displayed within.
Could you please explain to me why this is happening so I can understand where the error occurs, and how to correct it?
# -*- coding:utf-8 -*-
# Imports
from tkinter import Tk, Menu, Canvas
from PIL import Image, ImageTk
# Function definitions
def deleteImage(canvas):
canvas.delete("all")
return
def loadImage(canvas, img):
filename = ImageTk.PhotoImage(img)
canvas.image = filename
canvas.create_image(0,0,anchor='nw',image=filename)
return
def quitProgram():
gui.destroy()
# Main window
gui = Tk()
# Inside the main gui window
#Creating an object containing an image
# A canvas with borders that adapt to the image within it
img = Image.open("fleur.jpg")
canvas = Canvas(gui,height=img.size[0],width=img.size[0])
canvas.pack()
# Menu bar
menubar = Menu(gui)
# Adding a cascade to the menu bar:
filemenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Files", menu=filemenu)
# Adding a load image button to the cascade menu "File"
filemenu.add_command(label="Load an image", command=loadImage)
# Adding a delete image button to the cascade menu "File"
filemenu.add_command(label="Delete image", command=deleteImage)
filemenu.add_separator()
filemenu.add_command(label="Quit", command=quitProgram)
menubar.add_separator()
menubar.add_cascade(label="?")
# Display the menu bar
gui.config(menu=menubar)
gui.mainloop()
EDIT:
The second problem is that I want to create a canvas and the image in the main gui window, and pass them as arguments to the menu buttons (See code above, where img and canvas are created separately from the function loadImage). Seeing as putting parenthesis in the command=loadImage() created a problem on its own.
Another point that rises a question in my head : Regarding the first problem which was solved by keeping a reference to the filename=ImageTk.PhotoImage(img). Wouldn't it normally be pointless to keep a reference inside the function since it's a local variable anyway?
As stated in effbot's PhotoImage page, you have to keep a reference of your image to ensure it's not garbage collected.
You must keep a reference to the image object in your Python program,
either by storing it in a global variable, or by attaching it to
another object.
Note: When a PhotoImage object is garbage-collected by Python (e.g.
when you return from a function which stored an image in a local
variable), the image is cleared even if it’s being displayed by a
Tkinter widget.
To avoid this, the program must keep an extra reference to the image
object. A simple way to do this is to assign the image to a widget
attribute, like this:
Your loadImage() method should look like below.
def loadImage():
img = Image.open("fleur.jpg")
filename = ImageTk.PhotoImage(img)
canvas = Canvas(gui,height=100,width=100)
canvas.image = filename # <--- keep reference of your image
canvas.create_image(0,0,anchor='nw',image=filename)
canvas.pack()
I'm noticing a pretty strange bug with tkinter, and I am wondering if it's because there's something in how the python interacts with the tcl, at least in Win32.
Here I have a super simple program that displays a gif image. It works perfectly.
from Tkinter import *
canvas = Canvas(width=300, height=300, bg='white')
canvas.pack()
photo=PhotoImage(file=sys.argv[1])
canvas.create_image(0, 0, image=photo, anchor=NW) # embed a photo
print canvas
print photo
mainloop( )
Now, I change the program slightly to edit the canvas object from within a function. This time, I just get a blank canvas.
# demo all basic canvas interfaces
from Tkinter import *
canvas = Canvas(width=300, height=300, bg='white')
canvas.pack()
def set_canvas(cv):
photo=PhotoImage(file=sys.argv[1])
cv.create_image(0, 0, image=photo, anchor=NW) # embed a photo
print cv
print photo
set_canvas(canvas)
mainloop( )
The only difference between the two is that in one the canvas object is passed to a function instead of being used directly. Both print statements return identical results. I am wondering if there is perhaps some breakdown in the object model at the tcl/python layer.
Any thoughts, folks?
Thanks,
/YGA
Do that as a quick solution, and I'll try to explain:
def set_canvas(cv):
global photo # here!
photo=PhotoImage(file=sys.argv[1])
cv.create_image(0, 0, image=photo, anchor=NW) # embed a photo
print cv
print photo
A PhotoImage needs to have at least one reference from any Python object, otherwise it's garbage collected. In my solution, I suggest to make photo be a module-level name, so when the function ends, there will still be a reference to the PhotoImage object. You might prefer to create a class and make set_canvas into a method, and store the PhotoImage object as an instance variable.