I want to make a GUI where I have two buttons: from one button I can select an image and from the other button I can show the image with cv2.imshow
. I want to use cv2.imshow
because later I want to process the image with cv2
. Here is my code:
import tkinter as tk
import tkinter.filedialog as fd
import cv2
def select(label):
filepath = fd.askopenfilename()
text = "Selected image: {}".format(filepath)
label.config(text=text)
return filepath
def show_image(image_path):
image = cv2.imread(image_path)
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
root = tk.Tk()
root.geometry("600x400")
frame = tk.Frame(root)
frame.pack()
label_frame = tk.LabelFrame(frame)
label_frame.grid()
label = tk.Label(frame, text="Label")
label.grid()
func1 = lambda: select(label)
button1 = tk.Button(frame, text="select", command=func1)
button1.grid()
func2 = lambda: show_image(func1)
button2 = tk.Button(frame, text="show", command=func2)
button2.grid()
root.mainloop()
I have tried many things, for example change command=func2
to command=show_image
, but nothing seems to work. I think that the image path variable in show_image(image_path)
is a function because it is defined with lambda. Could I somehow convert the output to a string, so that the function works properly? I need to use lambda because I need to pass arguments to button command.
>Solution :
It looks like you’re passing the image_path
to the show_image
function through your func2
lambda. When you set func2 = lambda: show_image(func1)
, calling func1
inside show_image doesn’t return the filepath string as you might expect. Instead, it calls select(label)
which returns the filepat
h, but then you’re not using this returned filepath
correctly as an argument to show_image. You’re essentially trying to show func1
itself, not its result.
To fix this, you can modify your approach to ensure that func2
receives the filepath as a string from select(label) and then passes it correctly to show_image. You can try something like this:
import tkinter as tk
import tkinter.filedialog as fd
import cv2
def select(label):
filepath = fd.askopenfilename()
text = "Selected image: {}".format(filepath)
label.config(text=text)
return filepath
def show_image(image_path):
image = cv2.imread(image_path)
cv2.imshow("Image", image)
cv2.waitKey(0)
cv2.destroyAllWindows()
root = tk.Tk()
root.geometry("600x400")
frame = tk.Frame(root)
frame.pack()
label_frame = tk.LabelFrame(frame)
label_frame.grid()
label = tk.Label(frame, text="Label")
label.grid()
# Use a global variable to store the selected filepath
selected_filepath = None
def update_filepath():
global selected_filepath
selected_filepath = select(label)
def display_image():
global selected_filepath
if selected_filepath:
show_image(selected_filepath)
button1 = tk.Button(frame, text="select", command=update_filepath)
button1.grid()
button2 = tk.Button(frame, text="show", command=display_image)
button2.grid()
root.mainloop()