Pass result of clicking tkinter button to another button

Advertisements

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

Leave a ReplyCancel reply