Tkinter will only display the first photo I select via filedialog.askopenfilename - python

I have a program that allows the user to select an image from their PC and then displays it. The problem is that it only works once. The first photo is displayed but if I select/open another, I would think that this photo would then appear on top of the original but it doesn't.
Any idea why?
root = tk.Tk()
root.geometry("500x500")
root.title('Color Comparer')
picture_chooser_btn = tk.Button(master=root, text='Select Image', command= lambda: open_image())
picture_chooser_btn.pack()
base_color_picker_btn = tk.Button(master=root, text='Choose Base Color', command= lambda: selectBaseColor())
base_color_picker_btn.pack()
canvas = Canvas(root, width=80, height=50, bg="#F8F9F9")
base_color_rect = canvas.create_rectangle(0, 0, 85, 85, fill="red")
canvas_label = canvas.create_text((42, 20), text="Base Color")
canvas.pack()
label = tk.Label(root, anchor="w")
label.pack(side="top", fill="x")
root.bind('<ButtonPress-1>', on_click)
root.mainloop()
The function used to grab the photo from PC:
def open_image():
global image_selected
path=filedialog.askopenfilename(filetypes=[("Image File",'.jpg .png .jpeg')])
im = Image.open(path)
im = im.resize((400, 400), Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(im)
myvar=Label(root,image = tkimage)
myvar.image = tkimage
myvar.pack()
myvar.lift()
label.configure(text="you selected an image")
print("you selected an image")
print(str(tkimage))
image_selected = True

You need to destroy the old label widget containing the previous image before you can display a new one.
I made some minor modifications to your function that allows the code to work as you described
myvar = None
def open_image():
global myvar
if myvar is not None:
myvar.destroy()
path=filedialog.askopenfilename(filetypes=[("Image File",'.jpg .png .jpeg')])
im = Image.open(path)
im = im.resize((400, 400), Image.ANTIALIAS)
tkimage = ImageTk.PhotoImage(im)
myvar=Label(root,image = tkimage)
myvar.image = tkimage
myvar.pack()
myvar.lift()
label.configure(text="you selected an image")
print("you selected an image")
print(str(tkimage))

Related

How to resize image with ImageTk/Image from PIL

Here is the full code
import tkinter as tk
from PIL import ImageTk, Image
def hide_screen():
window.overrideredirect(0)
window.iconify()
def screen_appear(event):
window.overrideredirect(1)
def callback(event):
window.geometry("+{0}+{1}".format(event.x_root,event.y_root))
window = tk.Tk()
window.geometry("400x200")
window.overrideredirect(True)
title_bar = tk.Frame(window, bg="#2c2c2c", bd=0)
title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
label1 = tk.Label(title_bar, text="Title Bar", fg="gold2", bg="#2c2c2c", font="Times")
close_button = tk.Button(title_bar, text="X", bg="red", command=window.destroy, bd=0)
minimise_button = tk.Button(title_bar, text="-", bg="red", command=hide_screen, bd=0)
window2 = tk.Canvas(window, bg="#1b1b1b", highlightthickness=0)
title_bar.pack(fill="x")
panel.pack(side=tk.LEFT)
close_button.pack(side=tk.RIGHT)
minimise_button.pack(side=tk.RIGHT)
window2.pack(expand=1, fill="x")
label1.pack(anchor=tk.CENTER)
title_bar.bind("<Map>", screen_appear)
title_bar.bind("<B1-Motion>", callback)
window.mainloop()
And here are the image lines
title_bar_logo = ImageTk.PhotoImage(Image.open("title_bar_logo.png"))
title_bar_logo = ImageTk.resize((250, 250), Image.ANTIALIAS)
panel = tk.Label(title_bar, image=title_bar_logo)
panel.pack(side=tk.LEFT)
i have tried soo many things but i can't get it to work
and i really hope you can find an answer for me
thank you in advance
I use it as example it working well:
logo = Image.open("title_bar_logo.png")
logo = logo.resize((20,15), Image.ANTIALIAS)
title_bar_logo=ImageTk.PhotoImage(logo)
use :
title_bar_logo
in your code

Dynamically changing images connected to the item in listbox

I would like to dynamically display image of selected item in listbox.
The name of the image store in folder is exactly like item with index [0] from my tuple in listbox
list1= Listbox(ViewFrame, height=15, width=75)
files = glob.glob('img\\*.jpg')
ImageFrame = LabelFrame(page1, text="Podgląd i parametry")
ImageFrame.grid(row=6, column=6, pady=10, padx=5)
path = files[list1.curselection()[0]]
img = ImageTk.PhotoImage(Image.open(path))
label = Label(ImageFrame)
label.image = img
label.configure(image=img)
Error:
path = files[list1.curselection()[0]]
IndexError: tuple index out of range
It seems to me that before I open the app nothing is selected, but I do not know how to fix it.
check is something is selected before load images.
when create the listbox add
list1.bind("<<ListboxSelect>>", on_item_selected)
then add the function
def (on_item_selected):
path = files[list1.curselection()[0]]
img = ImageTk.PhotoImage(Image.open(path))
label = Label(ImageFrame)
label.image = img
label.configure(image=img)
on open....
if list1.curselection():
path = files[list1.curselection()[0]]
img = ImageTk.PhotoImage(Image.open(path))
label = Label(ImageFrame)
label.image = img
label.configure(image=img)
Here's runnable code, but it's merely a more complete version of #1966bc's answer which I created because you have in your question isn't a MCVE:
import glob
from tkinter import *
from PIL import Image, ImageTk
def on_item_selected(event):
path = files[list1.curselection()[0]]
img = ImageTk.PhotoImage(Image.open(path))
label.image = img
label.configure(image=img)
root = Tk()
page1 = Frame(root)
page1.grid(row=0, column=0)
ViewFrame = Frame(page1)
ViewFrame.grid(row=0, column=0)
files = glob.glob('*.jpg')[:10] # Limit to first 10 for development.
listvar = StringVar(value=files)
list1= Listbox(ViewFrame, height=15, width=75, listvariable=listvar)
list1.grid()
ImageFrame = LabelFrame(page1, text="Podgląd i parametry")
ImageFrame.grid(row=6, column=6, pady=10, padx=5)
label = Label(ImageFrame) # Create placeholder.
label.grid()
list1.bind("<<ListboxSelect>>", on_item_selected)
root.mainloop()

How can i print some features in python opencv GUI?

I want to print the mean, height & width of an image in python openCV. Where i used two button (get photo and analysis image) and different GUI,one for getting the photo(def openphoto(): ) and another for printing those features(def feature(): ). But I'm getting error.
N.B. full code is too long.so, i used some part of it.
I've tried it in python openCV.
import tkinter as tk
from tkinter.filedialog import askopenfilename
import shutil
import os
from PIL import Image, ImageTk
window = tk.Tk()
window.title("Dr. Papaya")
window.geometry("500x510")
window.configure(background ="lightgreen")
title = tk.Label(text="Click below to choose picture for testing disease....", background = "lightgreen", fg="Brown", font=("", 15))
title.grid()
def feature():
window.destroy()
window1 = tk.Tk()
window1.title(" ")
window1.geometry("650x510")
window1.configure(background="lightgreen")
def exit():
window1.destroy()
#i want to print here
print("Mean : ",mean)
print("Heigth : ",heigth)
print("Width : ",width)
button = tk.Button(text="Exit", command=exit)
button.grid(column=0, row=9, padx=20, pady=20)
window1.mainloop()
def openphoto():
import cv2
import numpy as np
fileList = os.listdir(dirPath)
for fileName in fileList:
os.remove(dirPath + "/" + fileName)
fileName = askopenfilename(initialdir='', title='Select image for analysis ',
filetypes=[('image files', '.jpg')])
dst = " "
shutil.copy(fileName, dst)
load = Image.open(fileName)
#calculate the mean
mean=np.mean(load)
#calculate the height & width
height = np.size(load, 0)
width = np.size(load, 1)
render = ImageTk.PhotoImage(load)
img = tk.Label(image=render, height="250", width="500")
img.image = render
img.place(x=0, y=0)
img.grid(column=0, row=1, padx=10, pady = 10)
title.destroy()
button1.destroy()
button2 = tk.Button(text="Analyse Image", command=feature)
button2.grid(column=0, row=2, padx=10, pady = 10)
button1 = tk.Button(text="Get Photo", command = openphoto)
button1.grid(column=0, row=1, padx=10, pady = 10)
window.mainloop()
The variables are not in scope when you try to print them. This is an important programming principle so I suggest you read this introduction
You can make the variable global to make the them accessible outside of the function:
def openphoto():
global width, height, mean
[rest of code]

How to print values in GUI from image in python?

I'm new in GUI developing.Here i'hv created two GUI, one for taking photo and another for showing features.so,i'hv used two functions.but i don't know some things.Now i need two kinds of help from you.
1)what is the command for printing float value in GUI(not on console)?
2)How to calculate the value of mean,variance ,s.d. etc from a image and how to pass those values from one function to another function?
import tkinter as tk
from tkinter.filedialog
import askopenfilename
import shutil
import os
from PIL import Image, ImageTk
window = tk.Tk()
window.title(" ")
window.geometry("500x510")
window.configure(background ="lightgreen")
title = tk.Label(text="Click below to choose picture for testing disease....", background = "lightgreen", fg="Brown", font=("", 15))
title.grid()
def feature():
window.destroy()
window1 = tk.Tk()
window1.title(" ")
window1.geometry("650x510")
window1.configure(background="lightgreen")
def exit():
window1.destroy()
#i want to print some features of image e.g. Mean, variance,s.d. Etc.
button = tk.Button(text="Exit", command=exit)
button.grid(column=0, row=9, padx=20, pady=20)
window1.mainloop()
def openphoto():
import cv2
import numpy as np
dirPath = " "
fileList = os.listdir(dirPath)
for fileName in fileList:
os.remove(dirPath + "/" + fileName)
fileName = askopenfilename(initialdir='', title='Select image for analysis ',
filetypes=[('image files', '.jpg')])
dst = " "
shutil.copy(fileName, dst)
#this is the image
Photo = Image.open(fileName)
render = ImageTk.PhotoImage(photo)
img = tk.Label(image=render, height="250", width="500")
img.image = render
img.place(x=0, y=0)
img.grid(column=0, row=1, padx=10, pady = 10)
title.destroy()
button1.destroy()
button2 = tk.Button(text="Analyse Image", command=feature)
button2.grid(column=0, row=2, padx=10, pady = 10)
button1 = tk.Button(text="Get Photo", command = openphoto)
button1.grid(column=0, row=1, padx=10, pady = 10)
window.mainloop()
Okay, I took some more time to look into it.
Concerning the calculation of the values, your previous question did that correct, however the variables needed to be accessible globally. Concerning the displaying of a text, you have to add a tkinter text widget. If you want to add more calculated values, just google for numpy + 'value your want'.
I've taken your code and created a working example, see the code below. Note that I removed some stuff that wasn't neede for the example, so copy the lines you need to your own code. Also check out this reference for the text widget.
Result:
Code:
Note: I created 2 text widgets deliberately, to show 2 ways of implementing multiple texts
import tkinter as tk
from tkinter.filedialog import askopenfilename
import shutil
import os
from PIL import Image, ImageTk
window = tk.Tk()
window.title(" ")
window.geometry("500x510")
window.configure(background ="lightgreen")
title = tk.Label(text="Click below to choose picture for testing disease....", background = "lightgreen", fg="Brown", font=("", 15))
title.grid()
def feature():
window.destroy()
window1 = tk.Tk()
window1.title(" ")
### create a text widget, place it in window1 and insert the text
width_txt = tk.Text(window1, height=2, width=30, fg="RED", background = "lightgreen", relief="flat")
width_txt.grid(column=0, row=0)
width_txt.insert(tk.END, "Width: " + str(width))
height_txt = tk.Text(window1, height=2, width=30, fg="RED", background = "lightgreen", relief="flat")
height_txt.grid(column=0, row=1)
height_txt.insert(tk.END, "Height: " + str(height) + "\nMean: " + str(mean))
window1.geometry("650x510")
window1.configure(background="lightgreen")
def openphoto():
### this line makes the variables accessible everywhere
global width,height, mean
import numpy as np
fileName = askopenfilename(initialdir='', title='Select image for analysis ',
filetypes=[('image files', '.jpg')])
photo = Image.open(fileName)
#### calculate values
height = np.size(photo, 0)
width = np.size(photo, 1)
mean = np.mean(photo)
render = ImageTk.PhotoImage(photo)
img = tk.Label(image=render, height="250", width="500")
img.image = render
img.place(x=0, y=0)
img.grid(column=0, row=1, padx=10, pady = 10)
title.destroy()
button1.destroy()
button2 = tk.Button(text="Analyse Image", command=feature)
button2.grid(column=0, row=2, padx=10, pady = 10)
button1 = tk.Button(text="Get Photo", command = openphoto)
button1.grid(column=0, row=1, padx=10, pady = 10)
window.mainloop()

How to clear part of a tkinter Canvas and show something when submit is pressed?

I'm creating a simple madlib style game and I've come into a bit of a problem. I cannot get the canvas to clear and show the results.
The following code places an image as the background of a canvas. It then places labels and entry fields in 2 columns for all of the words to be inserted. There is a submit button at the bottom of the page. I can't figure out how to get it clear everything except the background image, so that it can display the story, with the users words inserted. If i place it in the callback(), it clears just the background and keeps everything else. I want the opposite.
from tkinter import *
from PIL import Image, ImageTk
canvas_width = 360
canvas_height = 525
file = r"C:\Users\kraak\Desktop\PyCharm Community Edition 2017.1.2\borderedpaper.GIF"
master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
old_img = PhotoImage(file=file)
new_img = old_img.subsample(3, 3)
canvas.create_image(-11, -10, anchor=NW, image=new_img)
canvas.create_window(0, 0, height=1, width=1, anchor=NW)
canvas.create_text(0, 0, text="Test")
e1 = Entry(canvas)
canvas.create_window(250, 60, window=e1, height=15, width=100)
label = Label(text="Enter an adjective.")
label.place(x=40, y=50)
e1.focus_set()
e2 = Entry(canvas)
canvas.create_window(250, 85, window=e2, height=15, width=100)
label = Label(text="Enter a nationality.")
label.place(x=40, y=75)
e2.focus_set()
def callback():
print("Pizza was invented by a " + (e1.get()) + " " + (e2.get()))
def answer():
button = Button(text="Submit.", command=callback)
button.place(x=150, y=460)
answer()
canvas.pack()
mainloop()
As Bryan Oakley suggested you can store the id's of the widgets you want to get rid of in a list to make it easier to destroy() them all in the callback() function. Here's showing the modification to your code that would do that—note the lines with a # ADDED comments.
from tkinter import *
from PIL import Image, ImageTk
canvas_width = 360
canvas_height = 525
file = r"C:\Users\kraak\Desktop\PyCharm Community Edition 2017.1.2\borderedpaper.GIF"
master = Tk()
canvas = Canvas(master, width=canvas_width, height=canvas_height)
canvas_entry_widgets = [] # ADDED
old_img = PhotoImage(file=file)
new_img = old_img.subsample(3, 3)
canvas.create_image(-11, -10, anchor=NW, image=new_img)
canvas.create_window(0, 0, height=1, width=1, anchor=NW)
canvas.create_text(0, 0, text="Test")
e1 = Entry(canvas)
canvas.create_window(250, 60, window=e1, height=15, width=100)
label = Label(text="Enter an adjective.")
label.place(x=40, y=50)
e1.focus_set()
canvas_entry_widgets.append(e1) # ADDED
e2 = Entry(canvas)
canvas.create_window(250, 85, window=e2, height=15, width=100)
label = Label(text="Enter a nationality.")
label.place(x=40, y=75)
e2.focus_set()
canvas_entry_widgets.append(e2) # ADDED
def callback():
print("Pizza was invented by a " + (e1.get()) + " " + (e2.get()))
# destroy the canvas entry widgets and clear the list # ADDED
while canvas_entry_widgets: # ADDED
widget = canvas_entry_widgets.pop() # ADDED
widget.destroy() # ADDED
def answer():
button = Button(text="Submit.", command=callback)
button.place(x=150, y=460)
answer()
canvas.pack()
mainloop()
Every widget has a destroy method which can be used to delete the widget. In your callback you can simply call this method for every widget:
def callback():
e1.destroy()
e2.destroy()
...
In your specific case, if you want to delete all the labels you will have to give them unique names. Or, to make this even easier, you can store all of your widgets and iterate over the list.

Categories