Display image with buttons/text in tkinter - python

I'm a beginner trying to use tkinter to create a GUI. I've adapted code from other sources for my own use.
At the moment I'm trying to display an image along with a button.
However, when running the code, only the image displays no matter where I move the button, the button isn't displayed.
Would be grateful for any help.
Additional functionality:
I'm looking to implement a function so that I can move the image around using coordinates, also a function that allows me to use .jpg instead of .png.
Thanks in advance!
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.init_window()
def init_window(self):
self.master.title("WindowName")
self.pack(fill = BOTH, expand = 1)
quitButton = Button(self, text = "quit", command=self.client_exit)
quitButton.place(x=400,y=400)
self.showImg()
def client_exit(self):
exit() # Or another function
def showImg(self):
self.grid(row=0)
self.columnconfigure(0,weight=1)
self.rowconfigure(0,weight=1)
self.original = Image.open('wire.png')
resized = self.original.resize((200, 200),Image.ANTIALIAS)
self.image = ImageTk.PhotoImage(resized)
self.display = Label(self, image = self.image)
self.display.grid(row=0)
root = Tk()
root.geometry("600x600")
app = Window(root)
root.mainloop()

Related

python canvas image not rendered

I followed a few tutorials and I am trying to implement a clean object oriented code for python gui. The idea of my project is opening an image and drawing circles on it with mouse click.
There are 2 issues:
1)
In the code below, the canvas does not render the image.the image should be taken from the user
In java there is a repaint function that is called by VM so that the contents of the frame can be updated. I couldn't find something in python (No, I am not willing to try adding timer function to redraw every second.)
2)
Besides HELLO is not printed even I press f key. The keylistener is also not working
I have done GUI with Java before but Python code looks very dirty comparing Java.
I would be grateful if you can help.
from tkinter import *
from PIL import Image, ImageTk
from tkinter import Tk, Canvas, Frame, BOTH
from tkinter import filedialog
class Example(Frame):
def __init__(self, container):
super().__init__()
self.container = container
self.canvas = None
self.initUI()
def initUI(self):
fname=filedialog.askopenfilename(title='"pen')
self.canvas = Canvas(self.container)
self.canvas.pack(anchor='nw', fill='both', expand=1)
self.canvas.focus_set()
self.canvas.bind("<ButtonRelease-1>", self.mouseReleased)
self.canvas.bind("<Key>", self.pressedkey)
image = Image.open(fname)
image = image.resize((400, 400))
image = ImageTk.PhotoImage(image)
image_id=self.canvas.create_image(0, 0, image=image, anchor='nw')
def mouseReleased(self, event):
self.canvas.create_oval(event.x-10, event.y-10, event.x+10, event.y+10, width=2, fill='blue')
def pressedkey(self,event):
pressedkey=str(repr(event.char))
print(pressedkey,type(pressedkey))
if pressedkey.__eq__("f"):
print("HELLO")
def main():
root = Tk()
ex = Example(root)
root.geometry("400x250+300+300")
root.mainloop()
if __name__ == '__main__':
main()

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 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()

Why it shows blank instead of picture in my Tkinter program?

I want to use Tkinter to display all the pictures in a specific directory, so I firstly code to show all the pictures from a given list
The code is:
import os
from Tkinter import *
from PIL import Image, ImageTk
class Application(Frame):
def add_pic_panel(self, pic):
img = ImageTk.PhotoImage(Image.open(pic))
label = Label(root, image = img)
print label
return label
def create_gui(self):
pics = ['1.jpg', '2.jpg']
for pic in pics:
self.add_pic_panel(pic)
pass
def __init__(self, master=None):
Frame.__init__(self, master)
self.pack()
self.create_gui()
root = Tk()
app = Application(master=root)
app.mainloop()
root.destroy()
Environment: Mac OS 10.9, Python 2.7.5
How could I display all the pictures in the list?
The code does not pack the label.
Should keep the reference for the image.
def add_pic_panel(self, pic):
img = ImageTk.PhotoImage(Image.open(pic))
label = Label(self.master, image=img)
label.img = img # to keep the reference for the image.
label.pack() # <--- pack
return label
BTW, add_pic_panel use root directly. It would be better to use self.master.
root.destroy() at the last line cause TclError when closing the window. Remove the line.

Categories