I am trying to draw text on Image where the user clicks.
Getting this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Admin\AppData\Local\Programs\Python\Python37-32\lib\tkinter\__init__.py", line 1705, in __call__
return self.func(*args)
File "C:/Users/Admin/PycharmProjects/ashish/td.py", line 35, in draw_text
cv2.putText(img, "OpenCV + Jurassic Park!!!", (event.x,event.y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
TypeError: Expected cv::UMat for argument 'img'
if __name__ == "__main__":
root = Tk()
frame = Frame(root, bd=2, relief=SUNKEN)
canvas = Canvas(frame, bd=0)
canvas.grid(row=0, column=0, sticky=N+S+E+W)
frame.pack(fill=BOTH,expand=1)
#adding the image
File = filedialog.askopenfilename(parent=root, initialdir="F:/",title='Choose an image.')
img = ImageTk.PhotoImage(Image.open(File))
canvas.create_image(0,0,image=img,anchor="nw")
#function to be called when mouse is clicked
def draw_text(event):
cv2.putText(img, "OpenCV + Jurassic Park!!!", (event.x,event.y), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
cv2.imshow("Text", img)
#mouseclick event
canvas.bind("<Button 1>",draw_text)
root.mainloop()
Your img is ImageTK object from tkinter but cv2 is not part of tkinter and cv2.putText doesn't work with ImageTK. It needs something different. cv2 has own function to read image and it creates object which you can use with cv2.putText().
But canvas has function to display text on top of image and you don't need cv2. But it can't be saved in file as image with text.
But Image has function to draw text on image and it can be saved in file.
So finally you don't need cv2.
I use Image.Draw to create object on which I can put text or draw line/square/etc.
After adding text I replace image on canvas.
This method create image with text which you can save in file (img.save())
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk, ImageDraw
# function to be called when mouse is clicked
def draw_text(event):
global imgtk
global cv_img
# create object for drawing
draw = ImageDraw.Draw(img)
# put text
draw.text((event.x,event.y), "ImageDraw + Jurassic Park!!!")
# replace old image
canvas.delete(cv_img_id)
imgtk = ImageTk.PhotoImage(img)
cv_img_id = canvas.create_image(0, 0, image=imgtk, anchor="nw")
if __name__ == "__main__":
root = Tk()
frame = Frame(root, bd=2, relief=SUNKEN)
frame.pack(fill=BOTH, expand=1)
canvas = Canvas(frame, bd=0)
canvas.grid(row=0, column=0, sticky=N+S+E+W)
#adding the image
file = filedialog.askopenfilename(parent=root, initialdir="F:/",title='Choose an image.')
img = Image.open(file)
imgtk = ImageTk.PhotoImage(img)
cv_img_id = canvas.create_image(0, 0, image=imgtk, anchor="nw")
#mouseclick event
canvas.bind("<Button 1>", draw_text)
root.mainloop()
Using canvas.create_text you can put text on top of image which you can move/remove later but it doesn't create image with text which you can save in file.
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk
# function to be called when mouse is clicked
def draw_text(event):
canvas.create_text((event.x,event.y), text="Canvas + Jurassic Park!!!")
if __name__ == "__main__":
root = Tk()
frame = Frame(root, bd=2, relief=SUNKEN)
frame.pack(fill=BOTH, expand=1)
canvas = Canvas(frame, bd=0)
canvas.grid(row=0, column=0, sticky=N+S+E+W)
#adding the image
file = filedialog.askopenfilename(parent=root, initialdir="F:/",title='Choose an image.')
imgtk = ImageTk.PhotoImage(Image.open(file))
canvas.create_image(0, 0, image=imgtk, anchor="nw")
#mouseclick event
canvas.bind("<Button 1>", draw_text)
root.mainloop()
Related
I've tried to do a star fractal drawing a star using tkinter and putting an image as a background.
from tkinter import *
from PIL import ImageTk, Image
import tkinter as tk
app = Tk()
app.title("Welcome")
img =Image.open('C:\\Users\\Stefa\\Downloads\\galaxy.jpeg')
bg = ImageTk.PhotoImage(img)
canvas_width=800
canvas_height=800
master = tk.Tk()
label = Label(app, image=bg)
label.place(x = 0,y = 0)
label2 = Label(app, text = "WELCOME TO OUR GALAXY",
font=("Times New Roman", 24))
label2.pack(pady = 50)
app.geometry(f"{canvas_width}x{canvas_height}")
can_widgt=Canvas(app, width=canvas_width, height= canvas_height)
can_widgt.pack()
points=[200,20,80,396,380,156,20,156,320,396]
can_widgt.create_polygon(points, outline='red',fill='cyan', width=6)
app.mainloop()
That's the code
However when i run it i want the star to be upon the background image. Any solutions for this ? Thanks
You need to create the image as a canvas object rather than as a label.
For example, this add the image to the top-left corner of the canvas, with the drawing on top of it:
can_widgt.create_image(0, 0, anchor="nw", image=bg)
from tkinter import *
import tkinter as tk
from PIL import ImageTk, Image
from tkinter import ttk
import kalkulasi
#making the window
root = Tk()
root.title('Estimasi Perjalanan Kereta Rute Tangerang-Depok')
root.minsize(400,400)
root.geometry('650x700')
#define image
image = Image.open('petafix.png')
#define image as bg
bg = ImageTk.PhotoImage(image)
# create canvas
main_canvas = Canvas(root, width=650, height=700)
main_canvas.pack(fill='both', expand=True)
# set img in canvas
main_canvas.create_image(325, 300, image=bg)
# add "Selamat Datang!" text
main_canvas.create_text(325, 25, text="Selamat Datang!", font=('Helvetica', 25))
# making resize "HITUNG" button image
hitung_button = Image.open('button.jpg')
hitung_button_resized = hitung_button.resize((75, 30), Image.ANTIALIAS)
new_hitung_button = ImageTk.PhotoImage(hitung_button_resized)
label_hitung_button = Label(root, image= new_hitung_button, border= 0, anchor='center')
label_hitung_button.pack()
# reposition the "hitung" button
button = Button(root, image= new_hitung_button, border= 0, highlightthickness= 0,)
button_window = main_canvas.create_window(300, 670, anchor='nw', window=button)
# making resizer function
def resizer(event):
global bg1, resized_bg, new_bg
# open the image
bg1 = Image.open('petafix.png)
# Resize the image
resized_bg = bg1.resize((event.width, event.height), Image.ANTIALIAS)
# define image again as new bg
new_bg = ImageTk.PhotoImage(resized_bg)
# add new bg back to the canvas
main_canvas.create_image(325, 300, image=new_bg)
root.bind('<Configure>', resizer)
root.mainloop()
I'm trying to make my GUI window's dynamic, but there is an error i can't figured out that when i run the program, the program want to run but it still not dynamic and in the terminal, there is an error says AttributeError: 'PhotoImage' object has no attribute 'read'.
I am beginner in tkinter. I have added a resizable background which is perfectly working. Have look to the code
'''
import tkinter as tk
from PIL import ImageTk, Image
homeWin = tk.Tk()
homeWin.geometry("400x400")
background = ImageTk.PhotoImage(file = "bg.png")
hw_canvas = tk.Canvas(homeWin, width = 400, height=400)
hw_canvas.pack(fill="both", expand=True)
bg = hw_canvas.create_image(0, 0, image = background, anchor = "nw")
def bg_resizable(e):
global image, resized, image2
# open image to resize it
image = Image.open("bg.png")
# resize the image with width and height of root
resized = image.resize((e.width, e.height), Image.LANCZOS)
image2 = ImageTk.PhotoImage(resized)
hw_canvas.create_image(0, 0, image=image2, anchor='nw')
homeWin.bind("<Configure>", bg_resizable)
homeWin.mainloop()
'''
but after placing a frame on the canvas it is not working.
I don't know why this is. Pleas help me with it!
'''
import tkinter as tk
from PIL import ImageTk, Image
homeWin = tk.Tk()
homeWin.geometry("400x400")
background = ImageTk.PhotoImage(file = "bg.png")
hw_canvas = tk.Canvas(homeWin, width = 400, height=400)
hw_canvas.pack(fill="both", expand=True)
bg = hw_canvas.create_image(0, 0, image = background, anchor = "nw")
def bg_resizable(e):
global image, resized, image2
# open image to resize it
image = Image.open("bg.png")
# resize the image with width and height of root
resized = image.resize((e.width, e.height), Image.LANCZOS)
image2 = ImageTk.PhotoImage(resized)
hw_canvas.create_image(0, 0, image=image2, anchor='nw')
homeWin.bind("<Configure>", bg_resizable)
sl_frame = tk.Frame(hw_canvas, bg="white", width= 200, height=500)
sl_frame.place(relx= 0.5, rely= 0.5, anchor="center")
homeWin.mainloop()
'''
"<Configure>" events get called for main window and all children!
Using the following can exclude child "<Configure>" events:
import tkinter as tk
from PIL import ImageTk, Image
def bg_resizable(e):
global image, resized, image2
# main window has no master
if e.widget.master:
return
# resize the image with width and height of root
resized = image.resize((e.width, e.height), Image.LANCZOS)
image2 = ImageTk.PhotoImage(resized)
hw_canvas.itemconfigure(bg, image=image2)
image = Image.open("bg.png") # open image once, global
homeWin = tk.Tk()
homeWin.geometry("400x400")
hw_canvas = tk.Canvas(homeWin, width = 400, height=400)
hw_canvas.pack(fill="both", expand=True)
bg = hw_canvas.create_image(0, 0, anchor='nw')
sl_frame = tk.Frame(hw_canvas, bg="white", width= 200, height=500)
sl_frame.place(relx= 0.5, rely= 0.5, anchor="center")
homeWin.bind("<Configure>", bg_resizable)
homeWin.mainloop()
Also, note because event fires when window is first shown, there is not need to handle background outside of event.
I am making an image viewer Tkinter GUI that opens all images in the default windows pictures folder, puts them in a list and then placing them on a label. here is the code:
from tkinter import *
import glob
from PIL import Image, ImageTk
images = [Image.open(file) for file in glob.glob("C:/Users/abdel/pictures/*.png")]
image_number = 0
root = Tk()
root.title("image viewer")
tkimage = ImageTk.PhotoImage(images[0].resize(250, 250))
label = Label(root, image=tkimage)
label.grid(row=0, column=0, columnspan=2)
def forward():
global image_number
global tkimage
image_number = int(image_number)+1
tkimage = ImageTk.PhotoImage(images[image_number])
global label
global button_forward
global button_backward
label.grid_forget()
label = Label(root, image=tkimage)
label.grid(row=0, column=0, columnspan=2)
def back():
global image_number
global tkimage
image_number = int(image_number)-1
tkimage = ImageTk.PhotoImage(images[image_number])
global label
global button_forward
global button_backward
label.grid_forget()
label = Label(root, image=tkimage)
label.grid(row=0, column=0, columnspan=2)
button_backward = Button(root, text="<<", command=back)
button_forward = Button(root, text=">>", command=forward)
button_forward.grid(row=1, column=1)
button_backward.grid(row=1, column=0)
root.mainloop()
but this error happens :
Traceback (most recent call last):
File "C:\Users\abdel\PycharmProjects\pythonProject\imageviewer.py", line 12, in <module>
tkimage = ImageTk.PhotoImage(images[0].resize(250, 250))
File "C:\Users\abdel\AppData\Local\Programs\Python\Python39\lib\site-packages\PIL\Image.py", line 1891, in resize
raise ValueError(
ValueError: Unknown resampling filter (250). Use Image.NEAREST (0), Image.LANCZOS (1), Image.BILINEAR (2), Image.BICUBIC (3), Image.BOX (4) or Image.HAMMING (5)
when i write this : (.resize(250, 250)) after the tkimage object this error happens:
Traceback (most recent call last):
File "C:\Users\abdel\PycharmProjects\pythonProject\imageviewer.py", line 12, in <module>
tkimage = ImageTk.PhotoImage(images[0]).resize(250, 250)
AttributeError: 'PhotoImage' object has no attribute 'resize'
when i use width and height parameters for the label itself, it cuts or doesn't display the whole image.
when i don't use the resizing method everything goes fine and the code works but with the real image size
is displayed which is inconvenient. how can i resize the image without these errors? and also how can i open all different formats of images not only png?
This seems like a pretty straightforward question, but i am having trouble displaying a jpg image when a button is clicked. Here is my code (without the button code for the sake of time):
from tkinter import *
#screen stuff here
canvas = Canvas(app)
canvas.grid(row = 0,column = 0)
photo = PhotoImage(file = "test.jpg")
canvas.create_image(0,0, image = photo)
def show_image():
global canvas
global photo
canvas.create_image(0,0, image = photo)
#button that calls the function down here
Thanks!
This works with Python2:
import Tkinter as tk
import ImageTk
def show_image():
x = canvas.create_image(125, 125, image=tk_img)
while True:
print('show')
canvas.itemconfigure(x, state=tk.NORMAL)
button.configure(text = 'Hide')
yield
print('hide')
canvas.itemconfigure(x, state=tk.HIDDEN)
button.configure(text = 'Show')
yield
root = tk.Tk()
canvas = tk.Canvas(root, width=250, height=250)
canvas.grid(row=0, column=0)
tk_img = ImageTk.PhotoImage(file='image.png')
button = tk.Button(
root, text="Show", command=show_image().next, anchor='w',
width=10, activebackground="#33B5E5")
button.grid(row=1, column=0)
root.mainloop()
In Python3, PhotoImage can open GIF, PPM/PGM images. To open other formats, you may need to install Pillow (a fork of the PIL project for Python3).