How to change image in a Label in python using tkinter? - python

I have an image in a label and I want that image to be changed when I press the button but instead of changing the image the window becomes blank:
from tkinter import *
from PIL import Image,ImageTk
import os
root = Tk()
root.state("zoomed")
def chng():
photo2 = ImageTk.PhotoImage(Image.open("upload.jpg"))
img.config(image = photo2)
img.grid()
photo = ImageTk.PhotoImage(Image.open("cat.jpg"))
img = Label(root,image = photo)
upload = Button(root, text= "Upload" ,height = 3, width = 12, command =
chng)
upload.grid( )
for col_num in range(root.grid_size()[1]):
root.columnconfigure(col_num, minsize=600)
for row_num in range(root.grid_size()[1]):
root.rowconfigure(row_num, minsize=60)
img.grid()
root.mainloop()

You have to keep a reference to the image.
def chng():
photo2 = ImageTk.PhotoImage(Image.open("upload.jpg"))
img.config(image = photo2)
img.photo_ref = photo2 # keep a reference
And you don't need the extra grid() call.

Try this:
def chng():
photo2 = ImageTk.PhotoImage(Image.open("upload.jpg"))
img.config(image = photo2)
img.grid()
root.update_idletasks()

import Tkinter as tk
from PIL import Image
class Application(tk.Frame):
def __init__(self, master=None):
tk.Frame.__init__(self, master)
self.grid(row=5,column=2)
self.createWidgets()
top = self.winfo_toplevel()
def createWidgets(self):
self.grid()
app = Application()
simge = tk.PhotoImage(file="bg.png")
hira1 = tk.Label(image=simge)
hira1.grid(row=0,column=0,rowspan=5)
def manu1(event):
simen1=tk.PhotoImage(file="bg1.png")
hira1.configure(image=simen1)
hira1(image=simen1)
hira1.bind("<Button 1>",manu1)
app.mainloop()

Related

What is the function used to update frame image automatically in python?

I asked this question before and the previous one linked to another question but it didn't solve the problem.
I have a number of images, which are updated frequently in a file.
The names of images are on the same pattern (e.g: img1.jpg , img2.jpg ...)
I am programming a GUI on python tkinter to start from the first image and automatically update after 30 second.
after many tries, I have no idea how to achieve that because mainloop()function freezes the GUI and the problem is that I need them in one GUI.
Here is the code I used to open and resize images:
from PIL import Image, ImageTk
x=1
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
load = Image.open("./images/img%s.jpg"%x)
load=load.resize((1350,800))
render = ImageTk.PhotoImage(load)
img = Label(self, image=render)
img.image = render
img.place(x=0, y=0)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
I tried to use label.after(3000,function) but no results came up so I deleted it from the code.
Is there any way to solve this problem?
Thanks in advance
Too big for the comments, But this is a working version of your code:
from tkinter import *
from PIL import Image, ImageTk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1 #assigning x to 1 to start with img1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS) #loading first img
self.render = ImageTk.PhotoImage(self.load) #instantiating first img
self.img = Label(self, image=self.render) #labelizing it
self.img.image = self.render #keeping reference
self.img.pack() #packing it because place(x=0,y=0) will lead to overwriting of image
self.master.after(3000,self.update) #calling the function continoursly
def update(self):
self.x+=1 #increasing the x by 1 over each call to function
if self.x < 9:
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render) #changing the image of label
self.master.after(3000,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()
Hope this helped, do let me know if any errors or doubts.
Cheers
This code solved my problem:
#from tkinter import *
from PIL import Image, ImageTk
import os
from tkinter import Frame,Label,BOTH,Tk
class Window(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
self.master = master
self.pack(fill=BOTH, expand=1)
self.x = 1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img = Label(self, image=self.render)
self.img.image = self.render
self.img.pack()
self.master.after(3000,self.update)
def update(self):
if self.x<len(os.listdir("./images/")):
self.x+=1
self.load = Image.open(f"./images/img{self.x}.jpg").resize((1350,800),Image.ANTIALIAS)
self.render = ImageTk.PhotoImage(self.load)
self.img.config(image=self.render)
self.master.after(3000,self.update)
else:
self.x=1
self.master.after(1,self.update)
root = Tk()
app = Window(root)
root.wm_title("Tkinter window")
root.geometry("1350x800")
root.mainloop()

How store event.width in a variable in python?

I have a script that displays the dimensions of the tkinter window and I was wondering how I can set those values into a variable?
Here is the code:
import tkinter as tk
from tkinter import PhotoImage
root = tk.Tk()
canvas = tk.Canvas(root)
canvas.pack(fill="both", expand=True)
def canvas_changed(event):
global WW
WW = event.width
global HH
HH = event.height
img = PhotoImage(file="competeButton.png")
foo = canvas.create_image(image=img, width=WW, height=HH)
foo.pack(fill="both", expand=True)
root.mainloop()
Many thanks in advance for any help.
There's nothing special you have to do. Data is data, whether it comes from a widget or a database or anything else.
Here's an example that saves the value to a global variable:
def canvas_changed(event):
global canvas_width
canvas_width = event.width
Create a class with all your image and the resizing of it. Then issue an if statement to call those values every time it changes. Here is an example of what you might do:
import tkinter as tk
from PIL import Image, ImageTk
class MainFrame(tk.Tk):
def __init__(self, *args, **kwargs):
super().__init__(*args, **kwargs)
self.canvas = tk.Canvas(self)
self.canvas.pack(fill=tk.BOTH, expand=1)
self.canvas.bind("<Configure>", self.resize)
self.img = ImageTk.PhotoImage(Image.open(r"competeButton.png"))
self.canvas_img = self.canvas.create_image(0, 0, anchor="nw", image=self.img)
def resize(self, event):
img = Image.open(r"competeButton.png").resize((event.width, event.height), Image.ANTIALIAS)
self.img = ImageTk.PhotoImage(img)
self.canvas.itemconfig(self.canvas_img, image=self.img)
if __name__ == "__main__":
main_frame = MainFrame()
main_frame.mainloop()

How to show image in tkinter using pillow with OOP

I am making a program where I need to at some point display an image onto a frame at the press of a button. I am using an object oriented approach but it won't display the image. If I do something like:
from tkinter import *
from PIL import Image, ImageTk
root = Tk()
pic = Image.open("image.jpg")
tkpic = ImageTk.PhotoImage(pic)
label = Label(root, image=tkpic)
label.pack()
root.mainloop()
that works fine. But if I create a frame and try to display the picture like this:
from tkinter import *
from PIL import Image, ImageTk
class picframe(Frame):
def __init__(self, parent):
Frame.__init__(self, parent)
button = Button(self, text="show", command=self.showpic)
button.pack()
def showpic(self):
pic = Image.open("image.jpg")
tkpic = ImageTk.PhotoImage(pic)
label = Label(self, image=tkpic)
label.pack()
root = Tk()
frame = picframe(root)
frame.pack()
root.mainloop()
When I press the button it expands the window as if it was trying to display the image but nothing shows up it just becomes a wider window. So what am I doing wrong?
Thank you in advance!
As the picture is created in a function the reference tkpic will be garbage collected when the function exits. You need to save a reference to the image:
def showpic(self):
pic = Image.open("image.jpg")
tkpic = ImageTk.PhotoImage(pic)
label = Label(self, image=tkpic)
label.image = tkpic # Save reference to image
label.pack()
Alternatively you can ensure the persistance of the image reference by making it an instance variable:
def showpic(self):
pic = Image.open("images/beer.png")
self.tkpic = ImageTk.PhotoImage(pic)
label = Label(self, image=self.tkpic)
label.pack()

Image not shown python tkinter

I want to input an image in my program, when I do this code
from tkinter import *
root = Tk()
image1 = PhotoImage(file='dog.gif')
label1 = Label(root, image=image1)
label1.pack()
root.mainloop()
The image will appear, but when I do this code
from tkinter import *
class Image():
def __init__(self, master):
self.master = master
self.display_image()
def display_image(self):
self.image = PhotoImage(file='dog.gif')
self.label1 = Label(self.master, image=self.image)
self.label1.pack()
if __name__ == '__main__':
root = Tk()
Image(root)
root.mainloop()
The window will appear but the image was not shown
If you create an image without keeping a strong reference somewhere, it will create a conflict between the garbage collector of Python and Tkinter : the reference stored in the Label prevents the complete destruction and the image will be blank.
Also, be careful to not override base classes like Image, you'd better rename your own class My_Image
A simple workaround is to create a global variable containing the image:
from tkinter import *
class My_Image():
def __init__(self, master):
self.master = master
self.display_image()
def display_image(self):
self.label1 = Label(self.master, image=label1_img)
self.label1.pack()
root = Tk()
label1_img = PhotoImage(file='dog.gif')
My_Image(root)
root.mainloop()
or you can even create a global variable to store the My_Image instance :
if __name__ == '__main__':
root = Tk()
img = My_Image(root)
root.mainloop()

How to update the image of a Tkinter Label widget?

I would like to be able to swap out an image on a Tkinter label, but I'm not sure how to do it, except for replacing the widget itself.
Currently, I can display an image like so:
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
root.mainloop()
However, when the user hits, say the ENTER key, I'd like to change the image.
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image = img)
panel.pack(side = "bottom", fill = "both", expand = "yes")
def callback(e):
# change image
root.bind("<Return>", callback)
root.mainloop()
Is this possible?
The method label.configure does work in panel.configure(image=img).
What I forgot to do was include the panel.image=img, to prevent garbage collection from deleting the image.
The following is the new version:
import Tkinter as tk
import ImageTk
root = tk.Tk()
img = ImageTk.PhotoImage(Image.open(path))
panel = tk.Label(root, image=img)
panel.pack(side="bottom", fill="both", expand="yes")
def callback(e):
img2 = ImageTk.PhotoImage(Image.open(path2))
panel.configure(image=img2)
panel.image = img2
root.bind("<Return>", callback)
root.mainloop()
The original code works because the image is stored in the global variable img.
Another option to do it.
Using object-oriented programming and with an interactive interface to update the image.
from Tkinter import *
import tkFileDialog
from tkFileDialog import askdirectory
from PIL import Image
class GUI(Frame):
def __init__(self, master=None):
Frame.__init__(self, master)
w,h = 650, 650
master.minsize(width=w, height=h)
master.maxsize(width=w, height=h)
self.pack()
self.file = Button(self, text='Browse', command=self.choose)
self.choose = Label(self, text="Choose file").pack()
self.image = PhotoImage(file='cualitativa.gif')
self.label = Label(image=self.image)
self.file.pack()
self.label.pack()
def choose(self):
ifile = tkFileDialog.askopenfile(parent=self,mode='rb',title='Choose a file')
path = ifile.name
self.image2 = PhotoImage(file=path)
self.label.configure(image=self.image2)
self.label.image=self.image2
root = Tk()
app = GUI(master=root)
app.mainloop()
root.destroy()
Replace 'cualitativa.jpg' for the default image you want to use.
Another solution that might be of help.
In my case, I had two tk.Tk() windows. When using ImageTk.PhotoImage(), the object defaults to setting its tk window to being the first one created. A simple fix to this is to pass the tk window that you want as such ImageTk.PhotoImage(img, master=your_window)
import tkinter as tk
from PIL import ImageTk, Image
if __name__ == '__main__':
main_window = tk.Tk()
second_window = tk.Tk()
main_canvas = Canvas(second_window)
main_canvas.pack()
filename = 'test.png'
img = Image.open(filename)
img = img.resize((300, 100), Image.ANTIALIAS)
logo = ImageTk.PhotoImage(img, master=second_window)
logo_label = Label(master=main_canvas, image=logo)
logo_label.image = logo
logo_label.pack()
main_window.mainloop()

Categories