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:
I followed the suggestion followed by expert furas, But nothing is happening in the Tkinter window. Although all the print values are being displayed.
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()
Related
First: In code below i want to use instead of default rectangle button, images prepared by myslef.
This generates some problems (mayby with reference)? This button does not appear as image, also i am not able to use function (name: load_frame_insert()) after click.
Second: I wonder to have 2 bbtns:
Normal: assets/insert_data.png
OnClick: assets/insert_data2.png
Could you help me?
PS. Doesn't work after moving from up-down code to code with functions
import pyodbc
import pandas as pd
import os
import tkinter as tk
from PIL import ImageTk
# DB connector
conn = pyodbc.connect('DRIVER={ODBC Driver 17 for SQL Server};'
'SERVER=onyx1905;'
'DATABASE=DW_15;'
'Trusted_Connection=yes')
# variables
name = os.getlogin()
cursor = conn.cursor()
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
global img_button_1
def image_button_1(size):
img = tk.PhotoImage(file="assets/insert_data.png")
img = img.subsample(size, size)
return img
#button img: insert_data
#button img: insert_data_on_click
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = ImageTk.PhotoImage(file="assets/xrdl_logo.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f" Hi {name}, please choose an action "),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
# btn code on 1st frame
tk.Button(
frame_main,
image=image_button_1(1),
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
).pack(pady=5)
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
conn.close()
other related topics but doesnt work
youtube tutorials
For the statement command=image_button_1(1), the image returned by image_button_1(1) will be garbage collected because there is no variable referencing it. That is why you get a button without image.
You need to save the reference of the image, for example using an attribute of the button as below:
image = image_button_1(1)
btn = tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=lambda: load_frame_insert()
)
btn.pack(pady=5)
btn.image = image # save the reference of the image
I removed three libraries.
I removed image_button_1 function
Added image = tk.PhotoImage(file="p1.png")
Added variable for Button
Change 5 to 25 .pack(pady=25)
Removed lambda and brace bracket command=load_frame_insert
Snippet:
import os
import tkinter as tk
running = True
bg_color_1 = "#205E61"
bg_button = "#1B4E51"
bg_button_ac = "#FFD966"
def clear_widgets(frame):
for widget in frame.winfo_children():
widget.destroy()
def load_main_frame():
clear_widgets(frame_insert)
frame_main.tkraise()
frame_main.pack_propagate(False)
# widget frame_main logo
logo_image = tk.PhotoImage(file="p2.png")
logo_widget = tk.Label(frame_main, image=logo_image, bg=bg_color_1)
logo_widget.image = logo_image
logo_widget.pack()
# label on 1st frame
tk.Label(
frame_main,
text=(f"Hi please choose an action"),
bg=bg_button,
fg="white",
font=("TkMenuFont", 12)
).pack(pady=10)
image = tk.PhotoImage(file="p1.png")
# btn code on 1st frame
btn= tk.Button(
frame_main,
image=image,
bd=0,
relief="groove",
compound=tk.CENTER,
bg=bg_color_1,
fg="yellow",
activeforeground="pink",
activebackground=bg_color_1,
font=("TkMenuFont", 12),
cursor="hand2",
text="",
command=load_frame_insert
)
btn.pack(pady=25)
btn.image = image
def load_frame_insert():
print("Hi XYZ")
# ini for app
main_app = tk.Tk()
main_app.title("SRD Loader")
main_app.eval("tk::PlaceWindow . center")
x = main_app.winfo_screenwidth() // 3
y = int(main_app.winfo_screenheight() * 0.1)
main_app.geometry('500x600+' + str(x) + '+' + str(y))
# frame look
frame_main = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
frame_insert = tk.Frame(main_app, width=500, height=600, bg=bg_color_1)
for frame in (frame_main, frame_insert):
frame.grid(row=0, column=0)
load_main_frame()
main_app.mainloop()
Screenshot:
I want to show images in the Listbox tkinter widget. My code looks like this:
mylist = Listbox(self.labelFrame3, yscrollcommand=self.yscrollbar.set, selectmode=SINGLE)
mylist.grid(row=0, column=0, rowspan=21, columnspan=21, sticky=(N, S, E, W))
img = Image.open('modeldata/photosamples/amanullahattamuhammad2.0.jpg') # PIL solution
img = img.resize((200, 200), Image.ANTIALIAS) # The (250, 250) is (height, width)
img = ImageTk.PhotoImage(img)
How to print this image in Listbox?
As someone mentioned in a comment you can't put images in a Listbox, but as I mentioned in another, you could use a Text widget instead because you can put images into them. Below is a relatively simple demonstration of how something like that can be done. Its two buttons illustrate how it can display just text or a combination of the two simultaneously. Text widget are actually very versatile.
Anyway, since presumably you want a scrollable list, the Text subclass named tkinter.scrolledtext is used instead of plain one to save work. Since it's a subclass, it can do anything its baseclass can do.
from pathlib import Path
from PIL import Image, ImageTk
import tkinter as tk
from tkinter.constants import *
from tkinter.scrolledtext import ScrolledText
class App:
def __init__(self, image_folder_path, image_file_extensions):
self.root = tk.Tk()
self.image_folder_path = image_folder_path
self.image_file_extensions = image_file_extensions
self.create_widgets()
self.root.mainloop()
def create_widgets(self):
self.list_btn = tk.Button(self.root, text='List Images', command=self.list_images)
self.list_btn.grid(row=0, column=0)
self.show_btn = tk.Button(self.root, text='Show Images', command=self.show_images)
self.show_btn.grid(row=1, column=0)
self.text = ScrolledText(self.root, wrap=WORD)
self.text.grid(row=2, column=0, padx=10, pady=10)
self.text.image_filenames = []
self.text.images = []
def list_images(self):
''' Create and display a list of the images the in folder that have one
of the specified extensions. '''
self.text.image_filenames.clear()
for filepath in Path(self.image_folder_path).iterdir():
if filepath.suffix in self.image_file_extensions:
self.text.insert(INSERT, filepath.name+'\n')
self.text.image_filenames.append(filepath)
def show_images(self):
''' Show the listed image names along with the images themselves. '''
self.text.delete('1.0', END) # Clear current contents.
self.text.images.clear()
# Display images in Text widget.
for image_file_path in self.text.image_filenames:
img = Image.open(image_file_path).resize((64, 64), Image.ANTIALIAS)
img = ImageTk.PhotoImage(img)
self.text.insert(INSERT, image_file_path.name+'\n')
self.text.image_create(INSERT, padx=5, pady=5, image=img)
self.text.images.append(img) # Keep a reference.
self.text.insert(INSERT, '\n')
image_folder_path = 'modeldata/photosamples'
image_file_extensions = {'.jpg', '.png'}
App(image_folder_path, image_file_extensions)
Here's it running on a folder on my computer with the images shown:
Whenever I run this code with a background Image the button grid gets misplaced and pushed towards the bottom. Fortunately, it works as intended when no background is added .I want them to cover the background when executed. Pictures for reference are added below. Your help is highly appreciated.
# importing the module
import tkinter.messagebox
from tkinter import *
import random
# importing the module
# initialising tkinter
class window(Frame):
def __init__(self,master = None):
Frame.__init__(self,master)
self.master = master
# initialising tkinter
# creating the window
root = Tk()
app = window(root)
root.geometry("630x630")
root.title('Odd Even Game')
C = Canvas(root, bg="blue", height=250, width=300)
filename = PhotoImage(file = "BG.png")
background_label = Label(root,image=filename)
background_label.place(x=0, y=0, relwidth=1, relheight=1)
C.pack()
frame = Frame(root)
frame.pack()
# creating the window
# image
level_1e = "p1.png"
level_1o = "pe.png"
level_2e = "r1.png"
level_2o = "re.png"
# image
def create_cards(odd_image,even_image,next_level,fno,order,suc,err,w,h):
rx = random.randint(0,order-1)
ry = random.randint(0,order-1)
for i in range(0,order):
for j in range(0,order):
if i == rx and j == ry:
create_button(i,j,suc,odd_image,next_level,fno,odd_image,w,h)
else:
create_button(i,j,err,even_image,next_level,fno,odd_image,w,h)
def second_level(fno):
fno.pack_forget()
frame2 = Frame(root)
frame2.pack()
suc = "Congratulations! You have cleared level 2..Keep Going Buddy!"
err = "Wrong Answer..Don't give up yet!"
create_cards(level_2o,level_2e,final_level,frame2,4,suc,err,157.5,157.5)
def final_level(fno):
fno.pack_forget()
root.geometry("700x700")
ap = App(root)
# creating a button function
def create_button(x,y,msg,picture,next_level,fno,odd,w,h):
if picture == odd:
image = PhotoImage(file=picture)
click = Button(fno, image=image, width= w, height=h, bd = 0,command = lambda : [score_update(),next_level(fno),tkinter.messagebox.showinfo( "Odd One Out Project",msg)])
click.image = image
click.grid( row = x, column = y)
else:
image = PhotoImage(file=picture)
click = Button(fno, image=image, width= w, height=h, bd = 0,command = lambda : [next_level(fno),tkinter.messagebox.showinfo( "Odd One Out Project",msg)])
click.image = image
click.grid( row = x, column = y)
# creating a button function
def create_frame(fno):
root.geometry("630x630")
fno.pack_forget()
frame = Frame(root)
frame.pack()
suc = "Congratulations! You have cleared level 1..Time to increas[![enter image description here][1]][1]e the difficulty!"
err = "Wrong Answer..Please Try again !!"
create_cards(level_1o,level_1e,second_level,frame,3,suc,err,200,200)
def intro():
root.geometry("630x630")
frame0 = Frame(root)
frame0.pack()
click = Button(frame0,text="Start!" ,command = lambda [create_frame(frame0),tkinter.messagebox.showinfo( "Odd One Out Project","The game has begun!!")])
click.pack()
intro()
# starting the widget
root.mainloop()
# starting the widget
The first image is the error. Second Image is the required output.
Note: I'm still a beginner in Python and Tkinter hence various terms and methods might be something out of my scope. Would be appreciated if taken into consideration.
In case needed, you might know that this is a tkinter project for picking the odd one out image out of A*A grid.
I got the answer myself so will be sharing for future use.
C = Canvas(root, bg="blue", height=250, width=300)
This part draws a canvas of 250*300 dimensions hence does not let the buttons draw over it.
just change it to,
C = Canvas(root, bg="blue", height=0, width=0)
for the desired result
Here is my full Python code:
from tkinter import *
import glob
import os
from PIL import Image, ImageTk, ImageGrab
import tkinter as tk
import pyautogui
import datetime
#date & time
now = datetime.datetime.now()
root = tk.Tk()
root.title("SIGN OFF")
root.minsize(840, 800)
# Add a grid
mainframe = tk.Frame(root)
mainframe.columnconfigure(0, weight=1)
mainframe.rowconfigure(0, weight=1)
mainframe.pack(pady=100, padx=100)
# Create a Tkinter variable
tkvar = tk.StringVar(root)
# Directory
directory = "C:/Users/eduards/Desktop/work/data/to-do"
choices = glob.glob(os.path.join(directory, "*.jpg"))
tkvar.set('...To Sign Off...') # set the default option
# Dropdown menu
popupMenu = tk.OptionMenu(mainframe, tkvar, *choices)
tk.Label(mainframe, text="Choose your sign off here:").grid(row=1, column=1)
popupMenu.grid(row=2, column=1)
label2 = tk.Label(mainframe, image=None)
label2.grid(row = 4, column = 1, rowspan = 10)
# On change dropdown callback.
def change_dropdown(*args):
""" Updates label2 image. """
imgpath = tkvar.get()
img = Image.open(imgpath)
img = img.resize((240,250))
photo = ImageTk.PhotoImage(img)
label2.image = photo
label2.configure(image=photo)
tk.Button(mainframe, text="Open", command=change_dropdown).grid(row=3, column=1)
def var_states():
text_file = open("logfile.txt", "a")
text_file.write("TIME: %s, USER: %s, One %d, Two %d\n" % (now,os.getlogin(), var1.get(), var2.get()))
text_file.close()
print("One %d, Two %d" % (var1.get(), var2.get()))
var1 = IntVar()
Checkbutton(mainframe, text="Ingredients present in full (any allergens in bold with allergen warning if necessary)", variable=var1).grid(column = 2, row=1, sticky=W)
var2 = IntVar()
Checkbutton(mainframe, text="May Contain Statement.", variable=var2).grid(column = 2, row=2, sticky=W)
var3 = IntVar()
Checkbutton(mainframe, text="Cocoa Content (%).", variable=var3).grid(column = 2, row=3, sticky=W)
var4 = IntVar()
Checkbutton(mainframe, text="Vegetable fat in addition to Cocoa butter", variable=var4).grid(column = 2, row=4, sticky=W)
var5 = IntVar()
Checkbutton(mainframe, text="Instructions for Use.", variable=var5).grid(column = 2, row=5, sticky=W)
var6 = IntVar()
Checkbutton(mainframe, text="Additional warning statements (pitt/stone, hyperactivity etc)", variable=var6).grid(column = 2, row=6, sticky=W)
var7 = IntVar()
Checkbutton(mainframe, text="Nutritional Information Visible", variable=var7).grid(column = 2, row=7, sticky=W)
var8 = IntVar()
Checkbutton(mainframe, text="Storage Conditions", variable=var8).grid(column = 2, row=8, sticky=W)
var9 = IntVar()
Checkbutton(mainframe, text="Best Before & Batch Information", variable=var9).grid(column = 2, row=9, sticky=W)
var10 = IntVar()
Checkbutton(mainframe, text="Net Weight & Correct Font Size.", variable=var10).grid(column = 2, row=10, sticky=W)
var11 = IntVar()
Checkbutton(mainframe, text="Barcode - Inner", variable=var11).grid(column = 2, row=11, sticky=W)
var12 = IntVar()
Checkbutton(mainframe, text="Address & contact details correct", variable=var12).grid(column = 2, row=12, sticky=W)
def user():
user_input = os.getlogin()
tk.Label(mainframe, text = user_input, font='Helvetica 18 bold').grid(row = 0, column = 1)
user()
def save():
# pyautogui.press('alt')
# pyautogui.press('printscreen')
# img = ImageGrab.grabclipboard()
# img.save('paste.jpg', 'JPEG')
var_states()
tk.Button(mainframe, text = "Save", command = save).grid(row = 20, column = 1)
root.mainloop()
When I run the code, there will be a dropdown of jpg files. Currently It shows the full directory like so:
I have created a post earlier on how to trim down the path and got something like this:
files = os.listdir("C:/Users/eduards/Desktop/work/data/to-do")
print(files)
But If I use that code above, it will not open the path when clicked open because it doesn't have the full path name.
What I am trying to do is, cut down the path name for display purposes and open the image by following the original full path.
As an example:
The current drop-down menu shows C:/Users/eduards/Desktop/work/data/to-do/img1.jpg
My desired result is img1.jpg but in the background open the whole path of above.
Copy comment: this is what I have tried
directory = os.path.splitdrive("C:/Users/eduards/Desktop/work/data/to-do")
choices = glob.glob(os.path.join(directory[1:], "*.jpg"))
, but says
expected str, bytes or os.Pathlike, not tuple.
Have added [1:] because the path is split into 2 and returning the 2nd part of it.
Question: Show only the filename in OptionMenu but get original full path from selection.
Create your own OptionMenu which holds from all images the full path in a dict and shows only the filename as options.
Define your own widget FileNameOptionMenu by inheriting from (tk.OptionMenu)
class FileNameOptionMenu(tk.OptionMenu):
def __init__(self, parent, directory, extension, callback):
Get from all images the full path and extract the filename.
Save every full path in a dict using the filename as key and the full path as value.
# Save result from `glob` in a `dict`
self.glob = {}
for fpath in glob.glob(os.path.join(directory, "*.{}".format(extension))):
filename, extension = os.path.splitext(os.path.split(fpath)[1])
self.glob[filename] = fpath
Define a variable which holds the selected option for later usage.
Init the inherited tk.OptionMenu with the list of the keys from the dict.
Pass the class method self.command as command=.
Save the callback for later usage.
self.selected = tk.StringVar(parent, 'Select a image...')
super().__init__(parent, self.selected, *list(self.glob),
command=self.command)
self.callback = callback
This class method get called on every click option selection.
On call, it calls the self.callback, which is ImageLabel.configure, with the full path of the selected option.
def command(self, val):
self.callback(image=self.glob.get(self.selected.get()))
Define your own widget ImageLabel by inheriting from (tk.Label).
This class extends the tk.Label.configure to handle .configure(image=<full path> instead of .configure(image=<image object>.
class ImageLabel(tk.Label):
def __init__(self, parent):
super().__init__(parent, image=None)
Overload the inherited class method tk.Label.configure.
Catch the name argument image= and replace the passed full path with a image object.
def configure(self, **kwargs):
key = 'image'
if key in kwargs:
# Replace the filepath with the image
fpath = kwargs[key]
img = Image.open(fpath)
img = img.resize((240, 250))
self._image = ImageTk.PhotoImage(img)
kwargs[key] = self._image
Call the original tk.Label.configure to show the image
super().configure(**kwargs)
Usage:
import tkinter as tk
from PIL import Image, ImageTk
import glob, os
class App(tk.Tk):
def __init__(self):
super().__init__()
self.label_image = ImageLabel(parent=self)
self.label_image.grid(row=2, column=0)
self.option_menu = \
FileNameOptionMenu(parent=self,
directory='C:/Users/eduards/Desktop/work/data/to-do',
extension='jpg',
callback=self.label_image.configure
)
self.option_menu.grid(row=0, column=0)
if __name__ == "__main__":
App().mainloop()
Tested with Python: 3.5
Im trying to set up simple frame work for a trashy hang man game, the images are named in series of 6 for each stage of failure. S0 is the beginning and S6, is the final stage.
Im trying to figure out how to upudate the photo.
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
i=0
frameLeft = Frame(root)
frameRight = Frame(root)
frameRight.pack(side=RIGHT)
frameLeft.pack(side=LEFT)
#frame Left
#function Declaration
entry1 = Entry(frameLeft)
entry1.pack()
def updatePhoto():
i = entry1.get()
img = ImageTk.PhotoImage(Image.open("S" + i + ".gif"))
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
labelInstruction = Label(frameLeft, text=entry1.get())
labelInstruction.pack()
submitButton = Button(frameLeft, text="Submit", command=updatePhoto)
submitButton.pack()
#frame Right
img = ImageTk.PhotoImage(Image.open("S" + str(i) + ".gif"))
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
root.mainloop()
Instead of these lines:
imgPanel = Label(frameRight, image = img)
imgPanel.pack(side=BOTTOM, fill=BOTH, expand=YES)
I was able to use these
imgPanel.configure(image=img)
imgPanel.image = img
I also changed the order of left and right side making right come first as it's a scripting language and requires declaration.