1

I am new to python & requesting help from experts in this community. I am trying to delete images from my Tkinter widget FrameLabel. I have followed many solutions provided on the StackOverflow, but unfortunately, I am unable to implement those solutions in my code. I need help in deleting the image I have uploaded on the window.


GUI working:

  • Click on Select
  • Browse the image
  • Upload the image
  • It will display in the LabelFrame shown as following:
    frame3 = tk.LabelFrame(pw_right, bd=2, text='Uploaded images')
    frame3.pack(side='left', anchor='nw')
    

Delete Button

DelButton = tk.Button(frame1, text ='Delete', command = button.on_click_del_button)
DelButton.grid(row=0, column=4)

Delete Function:

def on_click_del_button(self):
    print('Delete button clicked')

    image = self.paths[self.radio_var.get()]

    if os.path.exists(image):
        os.remove(image)
    else:
        print("The file does not exist")

Help required section: I need help in defining Delete Function i.e button.on_click_del_button so that when I press delete. Tkinter deletes the selected image from the window.

Below is the GUI for the window: enter image description here

I followed the suggestion followed by expert furas, But nothing is happening in the Tkinter window. Although all the print values are being displayed.

enter image description here

2
  • Do you actually want to delete the file from the filesystem, or remove the corresponding radio button from the "uploaded images" label frame? Or both? Or something else? Please, clarify. Commented Dec 20, 2019 at 12:15
  • I want to do both. from the filesystem and remove the selected image corresponding radio button from the "uploaded images" label frame Commented Dec 20, 2019 at 13:10

1 Answer 1

3

You don't have to load image to delete from disk - you need only path

    image = self.paths[self.radio_var.get()]

and you have to use variable image, not string "image"

BTW: you don't need lambda to assing this function

command=button.on_click_del_button

and you don't need path='None', image='None' if you don't send values as arguments.


def on_click_del_button(self):
    print('Delete button clicked')

    image = self.paths[self.radio_var.get()]

    if os.path.exists(image):
        os.remove(image)
    else:
        print("The file does not exist")

To hide widget from window you have widget.pack_foger() and widget.grid_forget(). It hides so you can show it again using widget.pack() or widget.grid(...).

To remove widget from window and from memory - so you can't use it again - you have widget.destroy() like

 self.radio_handle[0].destroy()

but you would have to know which radiobutton was selected 0, 1 or 2.

Maybe better use path to keep elements in dictionary, not on list

 self.radio_handle[path] = radio_button

and later in on_click_del_button

 self.radio_handle[path].destroy()

You could also use path as value in Radiobutton

 tk.Radiobutton(..., value=path)

EDIT: It remove image from window.

I use StringVar() instead of IntVar()

self.radio_var = tk.StringVar()

and assign path as value in Radiobutton

Radiobutton(..., value=path)

so now it can return path instead of numer and it can be easier to find object in dictionary

self.radio_handle = dict()

Using list and numbers it could be problem because after removing element from list other elements change position on list and it could make problem.

Now I can add widget to dictionary

    self.radio_handle[path] = (radio_button)

and the same way I can destroy it

    def on_click_del_button(self):
        print('Delete button clicked')

        path = self.radio_var.get()
        self.radio_handle[path].destroy()        

import os
import tkinter as tk
from tkinter import filedialog
from tkinter import messagebox

import cv2
from PIL import Image
from PIL import ImageTk


class Button:

    def __init__(self, root, frame3):
        self.root = root
        self.frame3 = frame3

        self.radio_var = tk.StringVar()
        self.path_selected = '' # or None

        self.paths = []

        self.radio_handle = dict()
        self.check_value = []

    def on_click_select_button(self, fname_label):
        print('select button clicked')
        fileType = [('jpg/png file', ('*.jpg', '*.png'))]
        self.path_selected = filedialog.askopenfilename(filetypes=fileType)
        fname_label['text'] = os.path.basename(self.path_selected)

    def on_click_upload_button(self, path='None', image='None'):
        print('upload button clicked')

        if path == 'None':
            path = self.path_selected
        else:
            cv2.imwrite(path, image)

        if path in self.paths:
            messagebox.showerror('Upload Error', '"'
                                 + path
                                 + '"' + ' is already uploaded.')
        else:
            self.paths.append(path)
            self.create_radio_button(path)

    def on_click_show_button(self, method):
        print('showButton clicked')
        image = cv2.imread(self.paths[self.radio_var.get()])

        file_name = os.path.basename(self.paths[self.radio_var.get()])
        name, ext = os.path.splitext(file_name)
        path = 'images/' + name + '_' + method + ext


    def create_radio_button(self, path):

        image = cv2.imread(path)
        # image = cv2.resize(image,(120,120))
        image = self.scale_to_height(image, 120)
        image_tk = self.to_tk_image(image)

        radio_button = tk.Radiobutton(self.frame3, image=image_tk,
                                      value=path,
                                      variable=self.radio_var)
        self.radio_var.set('')
        self.radio_handle[path] = (radio_button)
        self.check_value.append(self.radio_var)

        radio_button.grid(row=(len(self.radio_handle) - 1) // 3,
                          column=(len(self.radio_handle) - 1) % 3)
        self.root.mainloop()

    def to_tk_image(self, image_bgr):
        image_rgb = cv2.cvtColor(image_bgr, cv2.COLOR_BGR2RGB)
        image_pil = Image.fromarray(image_rgb)
        image_tk = ImageTk.PhotoImage(image_pil)
        return image_tk

    def on_click_del_button(self):
        print('Delete button clicked')

        path = self.radio_var.get()

        if path:
            self.radio_handle[path].destroy() # remove widget from window
            del self.radio_handle[path] # remove from dictionary 
            self.paths.remove(path) # remove path from list
            self.radio_var.set('')
        else:
            print('Not selected')

        #image = path # self.paths[self.radio_var.get()]

        #if os.path.exists(image):
        #    os.remove(image)
        #else:
        #    print("The file does not exist")


    def scale_to_height(self, img, height):
        scale = height / img.shape[0]
        return cv2.resize(img, dsize=None, fx=scale, fy=scale)

if __name__ == '__main__':
    os.makedirs('images', exist_ok=True)

    root = tk.Tk()
    root.title('Image GUI')
    root.geometry('1280x960')

    pw_left = tk.Frame(root, relief='ridge', borderwidth=4)
    pw_left.pack(side='left', anchor='nw')

    pw_right = tk.Frame(root, relief='ridge', borderwidth=4)
    pw_right.pack(side='left', anchor='nw')

    frame1 = tk.Frame(pw_left, bd=2, relief="ridge")
    frame1.pack()

    frame2 = tk.LabelFrame(pw_left, bd=2, relief="ridge", text='options')
    frame2.pack(anchor='nw')

    frame3 = tk.LabelFrame(pw_right, bd=2, text='Uploaded images')
    frame3.pack(side='left', anchor='nw')

    button = Button(root, frame3)

    # add label
    label = tk.Label(frame1, text='File:')
    label.grid(row=0, column=0)

    # label to show file name
    file_name_label = tk.Label(frame1, text='-----not selected-----', width=20, bg='white')
    file_name_label.grid(row=0, column=1)

    # file select button
    select_button = tk.Button(frame1, text='select',
                              command=lambda: button.on_click_select_button(file_name_label))
    select_button.grid(row=0, column=2)

    # upload button
    uploadButton = tk.Button(frame1, text='Upload',
                             command=lambda: button.on_click_upload_button())
    uploadButton.grid(row=0, column=3)

    DelButton = tk.Button(frame1, text='Delete', command=button.on_click_del_button)
    DelButton.grid(row=0, column=4)

    root.mainloop()
Sign up to request clarification or add additional context in comments.

7 Comments

hi @furas, Thanks for your support. But, when I tried to follow the above instructions the image is not getting deleted from the frame. It is printing the Print output values in terminal but nothing is happening in the GUI.
Hi @furas, I have modified the code as suggested by you. but still facing the issue. Image is not getting deleted from the frame but in print, it is displaying the output as shown in the above image.
this code delete only from disk. os.remove() and os.path.exists() (which you used) are for deleting on disk, not in window. If you put widget with pack() then use pack_forget() or destroy() to remove it. If you used .grid() then use grid_forget() or destroy() to remove it.
I think I have used pack(). everywhere. Don't know where to add 'pack_forget()' or 'destroy()'. Can you please help me with this. and thanks a lot. Previously your code very informative & well explained.
I added full code which removes widget from window, widget from list, and path from self.paths
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.