I created a function in Tkinter that imports an image. But the function seems to execute but I am not able to access the image object. why did the problem occur?
import tkinter
from PIL import ImageTk, Image
from tkinter import *
from tkinter import ttk
root = tkinter.Tk()
root.title("Guess Geek")
root.geometry("1280x720")
root.resizable(0, 0)
def importimg(x,y):
x=ImageTk.PhotoImage(file=y)
importimg('bgimg','main1.jpg')
bg = Label(root, image=bgimg, )
bg.place()
root.mainloop()
Welcome to StackOverflow! I know that you have already accepted an answer but I want to show you my take on your code:
import tkinter as tk
import tkinter.ttk as ttk
import PIL.ImageTk
import PIL.Image
root = tk.Tk()
root.title("Guess Geek")
root.geometry("1280x720")
root.resizable(0, 0)
def importimg(file_name):
return PIL.ImageTk.PhotoImage(PIL.Image.open(file_name))
bg_img = importimg('main1.jpg')
bg = ttk.Label(root, image=bg_img)
bg.grid(column=0, row=0)
root.mainloop()
So here's what I have changed in your code:
Instead of bringing al of tkinter and tkinter.ttk in the global scope, I imported only the module
I renamed tkinter as tk and tkinter.ttk as ttk for the convenience of having shorter names to use
I imported the PIL.ImageTk module without bringing them in the global scope just to be sure of where it came from
I imported the PIL.Image module without bringing them in the global scope because there is a tkinter.Image that would have overrode it if with kept both in the global scope (the way your code was written)
PIL.ImageTk.PhotoImage() first argument should an PIL's image (provided easily by Image.open()) and not just the file name
importimg() returns the object created from the class PIL.ImageTk.PhotoImage(). This will get assigned to bg_img
Instead of using the place() geometry manager, I've used the grid()'s one. It's generally recommended by the TkDocs website
If you have any questions don't hesitate to ask.
The idea behind the code is perfect.
The problem here is that the code is unable to assign the image to the variable bgimg and that is happening because in line 15 you have defined bgimg as a string and not as a variable
Instead of
importimg('bgimg','main1.jpg')
Try
bgmain = 0
importimg(bgimg,'')
The Program might not be able to find the directory of image. I would recommend you to use .open() method to define image location. With this you can also specify the Width and Height of the image
.open() method
path = ".\imagename.jpg" or ".\images\imgname.jpg" or "F:\New folder\imgname.jpg"
k = Image.open(path)
k = k.resize((300,300), Image.ANTIALIAS)
bgimg = ImageTk.PhotoImage(k)
LABEL = Label(bg="black", image=bgimg)
LABEL.place(height=300, width=300)
If you still can't figure out what the problem is just refer to the following
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
root.title("Guess Geek")
root.geometry("1280x720")
root.resizable(0, 0)
def importimg(x,y):
path = y
k = Image.open(path)
k = k.resize((400,400),Image.ANTIALIAS)
x=ImageTk.PhotoImage(k)
global bgimg
bgimg = x
bgimg = 0
importimg(bgimg,".\foldername\imagename.jpg")
bg = Label(root, image=bgimg )
bg.place(width=400, height=400, relx=0.05, rely=0.1)
root.mainloop()
Related
'''
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
from PIL import ImageTk, Image
root = tk.Tk()
root.geometry("1255x944")
toplevel_frame = ttk.Frame(root)
Title_frame = ttk.Frame(toplevel_frame)
img= tk.PhotoImage(file="logo.PNG")
img = img.subsample(5, 5)
lbl = tk.Label(Title_frame,image=img, compound = tk.LEFT)
lbl.image = img
lbl.grid(row=0,column=0,padx=20, pady=0)
root.mainloop()
'''
It is not showing any error but I am unable to show image inside a frame
As mentioned by #acw1668 in the comments, the frames namely toplevel_frame and Title_frame have not been rendered using any layout function(for more info).
The label with the image(i.e. lbl) is contained within the Title_frame which is within the toplevel_frame. So if the toplevel_frame and the Title_frame are not rendered any widget they contain also would not be rendered. Thus the label with the image(lbl) is not rendered.
This can simply be fixed by using any particular layout function to render these frames.
Using grid the two other lines to be added will look like this -:
toplevel_frame.grid(row=0,column=0)
Title_frame.grid(row=0,column=0)
NOTE: The two lines have to be added in the order they are defined, that is the frames have to be rendered in the order of their definition i.e. toplevel_frame frame first followed by the Title_frame frame followed by the lbl label. This will be more clear looking at the full code as provided below.
With the necessary changes done the full code will look something like this -:
# IMPORTS
import tkinter as tk
from tkinter import ttk
from tkinter import filedialog as fd
from PIL import ImageTk, Image
# ROOT INITIATION
root = tk.Tk()
root.geometry("1255x944")
# IMAGE OBJECT DEFINITION
img= tk.PhotoImage(file="logo.PNG")
img = img.subsample(5, 5)
# WIDGET DEFINITION
toplevel_frame = ttk.Frame(root)
Title_frame = ttk.Frame(toplevel_frame)
lbl = tk.Label(Title_frame,image=img, compound = tk.LEFT)
lbl.image = img
# LAYOUT MANAGEMENT
toplevel_frame.grid(row=0,column=0) # ADDED.
Title_frame.grid(row=0,column=0) # ADDED.
lbl.grid(row=0,column=0,padx=20, pady=0)
# STARTING THE ROOT MAINLOOP
root.mainloop()
NOTE: Further while deciding on the layout management function to use keep this in mind.
I want to put an image inside my dice function I would really appreciate if someone can tell me what I need to add so I can have the image as the background of the page
def dice():
tk = Tk()
tk.geometry('300x300')
img = PhotoImage(file='dicee.gif')
lb5 = Label(tk,image=img)
lb5.pack()
btn4=Button(tk,text="Roll The Dice",command=dice)
btn4.place(x=110,y=130)
tk.mainloop()
The error it shows me is:
self.tk.call(
_tkinter.TclError: image "pyimage1" doesn't exist
Actually there are two separate problems with your code. One is that you're creating multiple instances of Tk() which is problematic as #Bryan Oakley mentioned in a comment — create a Toplevel window widget instead.
The other issue is that you're creating the PhotoImage in a function, and since it's a local variable it will be garbage collected when the function returns (see Why does Tkinter image not show up if created in a function?)
Here's code showing how to fix both issues:
from tkinter import *
def dice():
tk = Toplevel() # Create new window.
tk.geometry('300x300')
img = PhotoImage(file='dicee.gif')
lb5 = Label(tk, image=img)
lb5.img = img # Save reference to image.
lb5.pack()
tk = Tk()
btn4 = Button(tk, text="Roll The Dice", command=dice)
btn4.place(x=110, y=130)
tk.mainloop()
I created a simple image opening program which opens the image selected from filedialog by clicking a button, but wherever I select another image it just appears under the current image
I want the next image selected to be replaced by the old image.
Plz help what should I do
from tkinter import *
from PIL import Image,ImageTk
from tkinter import filedialog
root=Tk()
root.title('Image')
def open():
global my_img
root.filename = filedialog.askopenfilename(initialdir='/GUI',title='Select A File',filetypes=(('jpg files','*.jpg'),('png files','*.png'),('all files','*.*')))
my_img = ImageTk.PhotoImage(Image.open(root.filename))
my_image_lbl = Label(image=my_img).pack()
my_btn = Button(root,text='Open File Manager',command=open).pack()
root.mainloop()
You should create the my_image_lbl outside open() and update its image inside the function:
from tkinter import *
from PIL import Image,ImageTk
from tkinter import filedialog
root=Tk()
root.title('Image')
def open():
filename = filedialog.askopenfilename(initialdir='/GUI',title='Select A File',filetypes=(('jpg files','*.jpg'),('png files','*.png'),('all files','*.*')))
if filename:
my_image_lbl.image = ImageTk.PhotoImage(file=filename)
my_image_lbl.config(image=my_image_lbl.image)
Button(root,text='Open File Manager',command=open).pack()
my_image_lbl = Label(root)
my_image_lbl.pack()
root.mainloop()
I'm using python3 and tkinter, the first code works but the second after I put it into a function it no longer shows the image and I want to know why
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("test")
canv = Canvas(root,width=500, height=500)
canv.pack()
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.create_image(0,0,anchor="nw",image=image)
root.mainloop()
second code:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
root.title("test")
def main():
canv = Canvas(root,width=500, height=500)
canv.pack()
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.create_image(0,0,anchor="nw",image=image)
main()
root.mainloop()
In order to properly display ImageTk.PhotoImage images, you need to keep a persistent reference to each of them (see this answer and the documentation).
When your code leaves the main() function, your image object is garbage-collected. One easy way to fix this is to store the image reference in the canvas object, so that it will not be garbage-collected as long as your canvas exists:
...
image = ImageTk.PhotoImage(Image.open("C:/Users/tomas/Desktop/carros/carro2.jpg"))
canv.img = image
...
I have loaded an image to tkinter label and that image is diplayed in that label.When i press the button i need to change that image.When the button is pressed older image is gone but the new image is not displayed
My code is
import Tkinter as tk
from PIL import Image, ImageTk
root = tk.Tk()
def change_pic(labelname):
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
print "updated"
vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()
In def change_pic(labelname), you need to add labelname.photo = photo1 to make sure photo1 not being garbage collected.
def change_pic(labelname):
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
labelname.photo = photo1
print "updated"
P.S. Looks like both labelname.photo = photo1 and labelname.image = photo1 work.
Check this out for more details: http://effbot.org/tkinterbook/label.htm
You can use the label to display PhotoImage and BitmapImage objects.
When doing this, make sure you keep a reference to the image object,
to prevent it from being garbage collected by Python’s memory
allocator. You can use a global variable or an instance attribute, or
easier, just add an attribute to the widget instance.
The following edits were made:
I have organised your code layout and simplified its
syntax where possible. These are to make your code easier to read.
Commonly we make the PIL objects a subset/children of tk.
So long it is a part of root (i.e. it is a child of the root
or any of its child widgets), your PIL objects will work.
Your working code is shown below:
import Tkinter as tk
from PIL import Image, ImageTk
def change_pic():
vlabel.configure(image=root.photo1)
print "updated"
root = tk.Tk()
photo = 'cardframe.jpg'
photo1 = "demo.jpg"
root.photo = ImageTk.PhotoImage(Image.open(photo))
root.photo1 = ImageTk.PhotoImage(Image.open(photo1))
vlabel=tk.Label(root,image=root.photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=change_pic)
b2.pack()
root.mainloop()
I got it working with one more line of code:
import tkinter as tk # I am using python 3 on windows so the tkinter is lowercased
from PIL import Image, ImageTk
root = tk.Tk()
def change_pic(labelname):
global photo1 # This is the only new line you need, I believe
photo1 = ImageTk.PhotoImage(Image.open("demo.jpg"))
labelname.configure(image=photo1)
print("updated") # Again I'm using python 3 on windows so syntax may differ.
root.update() # You don't need this statement in this case, but it never hurts
vlabel=tk.Label(root)
photo = ImageTk.PhotoImage(Image.open('cardframe.jpg'))
vlabel.configure(image=photo)
vlabel.pack()
b2=tk.Button(root,text="Capture",command=lambda:change_pic(vlabel))
b2.pack()
root.mainloop()
I believe that the code changes the image locally, so the global statement will change it on the project scope.