Trying to hide a label in tkinter after pressed a button - python-3.x

I'm trying to hide some labels in my code of tkinter.
I'm loading images and then I apply some pre-processing techinque by the moment.
The case is, i have three labels which were added to the widget called "miframe" and all those are in the same coordinates:
labelmaduro = Label(miframe, image=ruta_maduro).place(x=25, y=60)
labelpinton = Label(miframe, image=ruta_pinton).place(x=25, y=60)
labelverde = Label(miframe, image=ruta_verde).place(x=25, y=60)
All the labels are added to frame one over another, I'm finding a way of hide all those labels after push the button "Select Image" and when I pushed the button calle "Predict" show i.g the "labelmature".
I should hide all those labels when the program has already started, but by the moment i can't do that,
I tryed used label1.lower() place_forget()to hide those labels and to show it, I tryed mylabel.pack()
from tkinter import *
import cv2
from PIL import Image
from PIL import ImageTk
from tkinter import filedialog as fd
import numpy as np
def select_image():
# grab a reference to the image panels
global panelA, panelB
# open a file chooser dialog and allow the user to select an input
# image
#ocultar clase predecida anteriormente:
path = fd.askopenfilename()
# ensure a file path was selected
if len(path) > 0:
# load the image from disk, convert it to grayscale, and detect
# edges in it
image = cv2.imread(path)
median = cv2.medianBlur(image, 9)
#Resize
#BGT TO RGB
image = cv2.cvtColor(image, cv2.COLOR_BGR2RGB)
median = cv2.cvtColor(median, cv2.COLOR_BGR2RGB)
dim = (340, 257)
original = cv2.resize(image, dim, interpolation = cv2.INTER_AREA)
median = cv2.resize(median, dim, interpolation = cv2.INTER_AREA)
# Convertir imagenes al formato PIL
original = Image.fromarray(original)
median = Image.fromarray(median)
#Pass to ImageTk format
original = ImageTk.PhotoImage(original)
median = ImageTk.PhotoImage(median)
#if the panels are none
if panelA is None or panelB is None:
#El primer panel guarda la primera imagen
panelA = Label(image=original)
panelA.image = original
panelA
panelA.pack(side="left", padx=10, pady=10)
#the second panel show the pre-processed image
panelB = Label(image=median)
panelB.image = median
panelB.pack(side="right", padx=10, pady=10)
hideLabels()
#in other cases update the panels
else:
# update the pannels
panelA.configure(image=original)
panelB.configure(image=median)
panelA.image = original
panelB.image = median
hideLabels()
def hideGreen():
labelverde.place_forget()
def hideLabels():
hideGreen()
def showMature():
labelmaduro.pack() #show label after push Predict Button
#Initialize the main window
root = Tk()
root.configure(background='black')
root.title("Opencv test")
panelA = None
panelB = None
#Frame which contains the labels
miframe = Frame(bg="#0F2D80", width="200", height="200")
ruta_maduro = PhotoImage(file="maduro.png")
ruta_pinton = PhotoImage(file="pinton.png")
ruta_verde = PhotoImage(file="verde.png")
#Create labels to show and hidde according to the prediction
labelmaduro = Label(miframe, image=ruta_maduro).place(x=25, y=60)
labelpinton = Label(miframe, image=ruta_pinton).place(x=25, y=60)
labelverde = Label(miframe, image=ruta_verde).place(x=25, y=60)
#add frame to root
miframe.pack(side="right", anchor="n", padx=10)
#User buttons
btn2 = Button(root, text="Predict Button", command=showMature)
btn2.pack(side="bottom", fill="both", expand="yes", padx="10", pady="10")
btn = Button(root, text="Select Image", command=select_image)
btn.pack(side="bottom", fill="both", expand="yes", padx="10", pady="10")
root.resizable(0,0)
# kick off the GUI
root.mainloop()
I want to hide all those labels and show only one of them after pressing the "predict" button, but when the program has already started all those labels should be hided, therefore i should only show one label according the predicted class.

You have None values in all of those 3 Labels, that is because you're assigning Label's method place(..) return value to the objects of those Labels, as place returns None (same for pack or grid).
Always do,
labelmaduro = Label(miframe, image=ruta_maduro)
labelmaduro.place(x=25, y=60)
Or if you want no object for a Label and just want to assign it without modifying it further in your code then you can use it like this.
Label(miframe, image=ruta_maduro).place(x=25, y=60)
Now for hiding labels.
You don't need three labels to show / hide to achieve that kind of functionality. It can be done by modifying the image of the existing Label so in that case you just need one Label and configure it's image resource to different one depending on your need like so...
img_label.config(image=ruta_pinton)
Here is an example of changing images of a single Label from different Buttons.
from tkinter import *
root = Tk()
ruta_maduro = PhotoImage(file="maduro.png")
ruta_pinton = PhotoImage(file="pinton.png")
ruta_verde = PhotoImage(file="verde.png")
img_label = Label(root)
img_label.pack()
Button(root, text='maduro', command=
lambda: img_label.config(image=ruta_maduro)).pack()
Button(root, text='maduro', command=
lambda: img_label.config(image=ruta_pinton)).pack()
Button(root, text='maduro', command=
lambda: img_label.config(image=ruta_verde)).pack()
mainloop()

Related

Tkinter, How do I extract values from a slider, manipulate them and display them in a new grid on my tk window?

I have managed to create 3 sliders. Each slider controls the X, Y, and Z helical angles. I want to combine the three angles from the sliders into one np.array, manipulate that array and display the result in a new grid in the open window. I would like the result to update in real-time as the slider is moved.
I can manipulate the sliders, but I don't know how to a). combine the 3 results into one array b). manipulate those results c). display those results.
I am trying to update the slider values in two different grid locations and am failing at that. Here is the code I've written so far. Any feedback would be greatly appreciated!
import numpy as np
import tkinter as tk
from tkinter import ttk
# root window
root = tk.Tk()
root.geometry('900x800')
# root.attributes('-fullscreen', True)
root.resizable(True, True)
root.title('Slider Demo')
# slider current value
current_value_x = tk.DoubleVar()
current_value_y = tk.DoubleVar()
current_value_z = tk.DoubleVar()
def get_current_value():
return ['{: .2f}'.format(current_value_x.get()),
'{: .2f}'.format(current_value_y.get()),
'{: .2f}'.format(current_value_z.get())]
def slider_changed(event):
value_label_x.configure(text=get_current_value()[0])
value_label_y.configure(text=get_current_value()[1])
value_label_z.configure(text=get_current_value()[2])
# label for the slider
slider_label_helical_x = ttk.Label(root, text='Helical X:')
slider_label_helical_y = ttk.Label(root, text='Helical Y:')
slider_label_helical_z = ttk.Label(root, text='Helical Z:')
slider_label_helical_x.grid(column=0, row=0, sticky='w')
slider_label_helical_y.grid(column=0, row=1, sticky='w')
slider_label_helical_z.grid(column=0, row=2, sticky='w')
# slider
slider_x = ttk.Scale(root, from_=-180, to=180, orient='horizontal', command=slider_changed, variable=current_value_x)
slider_y = ttk.Scale(root, from_=-180, to=180, orient='horizontal', command=slider_changed, variable=current_value_y)
slider_z = ttk.Scale(root, from_=-180, to=180, orient='horizontal', command=slider_changed, variable=current_value_z)
slider_x.grid(column=1, row=0, sticky='we')
slider_y.grid(column=1, row=1, sticky='we')
slider_z.grid(column=1, row=2, sticky='we')
# Helical value label
value_label_x = ttk.Label(root, text=get_current_value()[0])
value_label_x.grid(column=2, row=0, sticky='n')
value_label_y = ttk.Label(root, text=get_current_value()[1])
value_label_y.grid(column=2, row=1, sticky='n')
value_label_z = ttk.Label(root, text=get_current_value()[2])
value_label_z.grid(column=2, row=2, sticky='n')
# Rotation Matrix Labels
rotationMatrixLabelHeader = ttk.Label(root, text='Rotation Matrix')
rotationMatrixLabel_1_1 = ttk.Label(root, text='(1,1)')
rotationMatrixValue_1_1 = ttk.Label(root, text=get_current_value()[0])
rotationMatrixLabelHeader.grid(column=0, row=3, sticky='w')
rotationMatrixLabel_1_1.grid(column=0, row=4, sticky='w')
rotationMatrixValue_1_1.grid(column=0, row=5, sticky='w')
root.mainloop()
So far, I have managed to place the 3 sliders where I want them, as well as their appropriate labels and outputs. In column 0, row 5, I'm trying to manipulate the value from the first slider and display that. At the moment, I can't even display the value from that slider, let alone manipulate it.
I have written a working solution from your original code. The below code shows the "original" Numpy array and the "changed" Nupmy array (reversed) in real time. The Matrix values are updated when you change one on sliders.
I have added several comments to the code where I have changed as explanation.
Code:
import numpy as np
import tkinter as tk
from tkinter import ttk
# root window
root = tk.Tk()
root.geometry("900x800")
# root.attributes('-fullscreen', True)
root.resizable(True, True)
root.title("Slider Demo")
# slider current value
current_value_x = tk.DoubleVar()
current_value_y = tk.DoubleVar()
current_value_z = tk.DoubleVar()
def get_current_value():
return [
"{: .2f}".format(current_value_x.get()),
"{: .2f}".format(current_value_y.get()),
"{: .2f}".format(current_value_z.get()),
]
def slider_changed(event):
current_values = get_current_value()
value_label_x.configure(text=current_values[0])
value_label_y.configure(text=current_values[1])
value_label_z.configure(text=current_values[2])
# Fill the numpy array with the "new" values when you change a slider.
# Probably here a float(X) casting would be nice.
np_arr = np.array([current_values[0], current_values[1], current_values[2]])
# Call the calculation and show method.
# You can implement the Array manipulations in this function.
calculate_and_show_matrix(np_arr)
def calculate_and_show_matrix(np_array):
"""
Here you can do anything with your Numpy array and show the value on the GUI.
Currently this function only show the original Numpy array and the reversed array.
#param np_array: The Numpy Array
#return: None
"""
# Set the "text" parameter of "rotationMatrixValue_1_1_orig" object to the "original" array value.
rotationMatrixValue_1_1_orig.configure(text="{}".format(np_array))
# This is the array manipulation (Reverse the array)
reversed_arr = np_array[::-1]
# Set the "text" parameter of "rotationMatrixValue_1_1_changed" object to the "changed" array value.
rotationMatrixValue_1_1_changed.configure(text="{}".format(reversed_arr))
# label for the slider
slider_label_helical_x = ttk.Label(root, text="Helical X:")
slider_label_helical_y = ttk.Label(root, text="Helical Y:")
slider_label_helical_z = ttk.Label(root, text="Helical Z:")
slider_label_helical_x.grid(column=0, row=0, sticky="w")
slider_label_helical_y.grid(column=0, row=1, sticky="w")
slider_label_helical_z.grid(column=0, row=2, sticky="w")
# slider
slider_x = ttk.Scale(
root, from_=-180, to=180, orient="horizontal", command=slider_changed, variable=current_value_x
)
slider_y = ttk.Scale(
root, from_=-180, to=180, orient="horizontal", command=slider_changed, variable=current_value_y
)
slider_z = ttk.Scale(
root, from_=-180, to=180, orient="horizontal", command=slider_changed, variable=current_value_z
)
slider_x.grid(column=1, row=0, sticky="we")
slider_y.grid(column=1, row=1, sticky="we")
slider_z.grid(column=1, row=2, sticky="we")
# Helical value label
value_label_x = ttk.Label(root, text=get_current_value()[0])
value_label_x.grid(column=2, row=0, sticky="n")
value_label_y = ttk.Label(root, text=get_current_value()[1])
value_label_y.grid(column=2, row=1, sticky="n")
value_label_z = ttk.Label(root, text=get_current_value()[2])
value_label_z.grid(column=2, row=2, sticky="n")
# Rotation Matrix Labels
rotationMatrixLabelHeaderOriginal = ttk.Label(root, text="Original rotation Matrix")
rotationMatrixValue_1_1_orig = ttk.Label(root)
rotationMatrixLabelHeaderChanged = ttk.Label(root, text="Changed rotation Matrix (Reversed)")
rotationMatrixValue_1_1_changed = ttk.Label(root)
rotationMatrixLabelHeaderOriginal.grid(column=0, row=3, sticky="w")
rotationMatrixValue_1_1_orig.grid(column=0, row=4, sticky="w")
rotationMatrixLabelHeaderChanged.grid(column=0, row=5, sticky="w")
rotationMatrixValue_1_1_changed.grid(column=0, row=6, sticky="w")
root.mainloop()
GUI:

Update canvas image on button click event

I'm trying to modify the displayed image on a canvas when a button is clicked on.
I have an object "Window" which will contain my window layers. this object contain a canvas named "draw_frame" and a button named "source_button". I add the command "self.load_static_source" to my button but when i click on my button nothing happen.
(Not exactely nothing because i tried to add default background in the init scope and when i click on my button after that the image on the canvas just diseappeared and the new selected image wasn't draw).
Here is my code:
from tkinter import *
from tkinter import filedialog
from PIL import Image, ImageTk
DARK_THEME = "grey"
LIGHT_THEME = "white"
THEME = LIGHT_THEME
class Window():
# object constructor
def __init__(self, root, theme):
# Sections #
self.toolbar_frame = LabelFrame(root, bg=theme, height="40")
self.toolbar_frame.pack(side=TOP, fill=X)
# Canvas #
self.draw_frame = Canvas(root)
self.draw_frame.pack(side=RIGHT, fill=BOTH, expand=True)
self.frame = self.draw_frame.create_image(0, 0, anchor=NW)
# Buttons #
self.source_button = Button(self.toolbar_frame, text="Source", bg=theme, command= lambda: self.load_static_source("./Sources/"))
self.source_button.pack(side=LEFT)
# Load image with tk compatibility
def load_image(self, path_):
print(path_) ### DEBUG ###
image = Image.open(path_)
return ImageTk.PhotoImage(image)
# Change canvas source with static one
def load_static_source(self, dir_):
path_ = filedialog.askopenfilename(initialdir = dir_, title = "Select file", filetypes = (("jpeg files","*.jpg"),("all files","*.*")))
self.draw_frame.itemconfig(self.frame, image=self.load_image(path_))
root = Tk()
Window(root, THEME)
root.mainloop()
I found an other post talking about that and i can't find difference between what i did and the given solution and that's why i don't understand why that code isn't working.
Here are the exemple i found and the related post:
from Tkinter import *
#----------------------------------------------------------------------
class MainWindow():
#----------------
def __init__(self, main):
# canvas for image
self.canvas = Canvas(main, width=60, height=60)
self.canvas.grid(row=0, column=0)
# images
self.my_images = []
self.my_images.append(PhotoImage(file = "ball1.gif"))
self.my_images.append(PhotoImage(file = "ball2.gif"))
self.my_images.append(PhotoImage(file = "ball3.gif"))
self.my_image_number = 0
# set first image on canvas
self.image_on_canvas = self.canvas.create_image(0, 0, anchor = NW, image = self.my_images[self.my_image_number])
# button to change image
self.button = Button(main, text="Change", command=self.onButton)
self.button.grid(row=1, column=0)
#----------------
def onButton(self):
# next image
self.my_image_number += 1
# return to first image
if self.my_image_number == len(self.my_images):
self.my_image_number = 0
# change image
self.canvas.itemconfig(self.image_on_canvas, image = self.my_images[self.my_image_number])
#----------------------------------------------------------------------
root = Tk()
MainWindow(root)
root.mainloop()
Related post : stackoverflow topic
You need to keep a reference to the image. Here's a link to the effbot page describing it: https://effbot.org/tkinterbook/photoimage.htm
You must keep a reference to the image object in your Python program, either by storing it in a global variable, or by attaching it to another object.
The solution Xeyes wrote is right, and this page explains.
So i found the solution. A bit weird but it works. I have to save the image in a class attribute before i give it to the canvas itemconfig method.
It now looks like :
self.placeholder = self.load_image(path_)
self.draw_frame.itemconfig(self.frame, image=self.placeholder)
Instead of just :
self.draw_frame.itemconfig(self.frame, image=self.load_image(path_))

Tkinter button doesn't work when I add an image on this button

I'm creating a button with tkinter but I want to had an image on this button. When I make it, the button doesn't work. Nonetheless, when I remove the image of my button, it works..
# Creating a photoimage object to use image
photo = PhotoImage(file = r"C:/Users/toto/Documents/toto/img/Flechedroiteverte.png")
# Resizing image to fit on button
photoimage = photo.subsample(1, 1)
PageSuivante=Button(main_win, text = 'Click Me !', image = photoimage)
PageSuivante.grid(pady = 10)
You have to keep a reference in a label, I have the same problem. You can do something like:
add = PhotoImage(file=r"C:/Users/toto/Documents/toto/img/Flechedroiteverte.png")
label = Label(image=add)
label.image = add # keep a reference!
PageSuivante=Button(main_win, text = 'Click Me !', image = add)
def ShowFramePrepaChantier(main_win,frame):
delete_frame(main_win)
frame.tkraise()
frame.place(x=0, y=0)
bouton_DownloadDPA = Button(frame, text='Valider mes DPA sélectionnées',padx = 200)
bouton_DownloadDPA.grid(row=1, column=0, sticky=SE)
bouton_DownloadDPA.bind('<Button-1>', select)
## Creating a photoimage object to use image
photo = PhotoImage(file = r"C:/Users/toto/Documents/toto/img/Flechedroiteverte.png")
# Resizing image to fit on button
photoimage = photo.subsample(10, 10)
# here, image option is used to
# set image on button
# compound option is used to align
# image on LEFT side of button
bouton = Button(frame, text = 'Click Me !', image = photoimage,
compound = LEFT)
bouton.grid(pady = 100)
if __name__ == "__main__":
main_win = Tk()
main_win.configure(bg='lavender')
main_win.title("Test")
main_win.geometry("680x400")
second_frame = Frame(main_win)
bouton_PrepaChantier = Button(main_win, text='Click to change frame', command=lambda:ShowFramePrepaChantier(main_win,second_frame), height=3, width=20)
bouton_PrepaChantier.grid()
main_win.mainloop()

Tkinter not able to fill the text box to the frame using grid. Used styling to add shadow and focus

Description
I am creating a canvas with scrollbar and adding frames with a text box in the frame and to fill the entire frame with no border. This will make it look as if the frame is the textbox. I have added shadow and styling to the frame (as coded by Bryan). This is added dynamically in for loop.
When I am trying to expand the text box to the frame, it is not expanding to fill the entire frame. There are extra spaces left.
Question
How do I fill up the entire frame with the textbox using a grid?
Code
import tkinter as tk
from tkinter import ttk
focusBorderImageData = '''
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
Ry/99NIz//oGrZpUUEAAOw==
'''
borderImageData = '''
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
'''
root = tk.Tk()
style = ttk.Style()
borderImage = tk.PhotoImage("borderImage", data=borderImageData)
focusBorderImage = tk.PhotoImage("focusBorderImage", data=focusBorderImageData)
style.element_create("RoundedFrame",
"image", borderImage,
("focus", focusBorderImage),
border=16, sticky="nsew")
style.layout("RoundedFrame",
[("RoundedFrame", {"sticky": "nsew"})])
root.configure(background="white")
canvas = tk.Canvas(root)
scroll = tk.Scrollbar(root, orient='horizontal', command=canvas.xview)
canvas.configure(xscrollcommand=scroll.set)
frame = tk.Frame(canvas) # frame does not get pack() as it needs to be embedded into canvas throught canvas.
scroll.pack(side='bottom', fill='x')
canvas.pack(fill='both', expand='yes')
canvas.create_window((0,0), window=frame, anchor='nw')
frame.bind('<Configure>', lambda x: canvas.configure(scrollregion=canvas.bbox('all'))) # lambda function
for i in range(5):
frame1 = ttk.Frame(frame, style="RoundedFrame", padding=10)
journal1 = tk.Text(frame1, borderwidth=2, highlightthickness=0, width = 40, height = 38)
# journal1.configure(borderwidth="3")
journal1.configure(relief="groove")
journal1.configure(background="white")
journal1.grid(row=0, column=0, padx=(100, 10), sticky = 'nswe') # grid instead
journal1.bind("<FocusIn>", lambda event: frame.state(["focus"]))
journal1.bind("<FocusOut>", lambda event: frame.state(["!focus"]))
frame1.grid_columnconfigure(0, weight=1)
frame1.grid_rowconfigure(0, weight=1)
frame1.grid(row=0,column=i, sticky = 'nswe')
root.mainloop()
Output
I had troubles with the focus of the frame, it complained frame has no attribute 'state'. It works in Bryans original answer. I fixed it with closures.
def frameFocusCreator(frame, focusState):
def changeState(event):
frame.state([focusState])
return changeState
for i in range(5):
frame1 = ttk.Frame(frame, style="RoundedFrame", padding=10)
journal1 = tk.Text(frame1, borderwidth=0, highlightthickness=0, width = 40, height = 38)
journal1.configure(relief="groove")
journal1.configure(background="white")
journal1.pack(fill='both', expand=True)
journal1.bind("<FocusIn>", frameFocusCreator(frame1, "focus"))
journal1.bind("<FocusOut>", frameFocusCreator(frame1, "!focus"))
frame1.grid(row=0,column=i, sticky = 'nswe')

Adding a background image to a root window and placing labels on the top of the background image

I'm trying to add a background image to my root window but it doesn't seem to be working for me. This is my code. I would like the background image to cover the whole window and place the labels on top of the background image.
from tkinter import *
from tkinter import messagebox
top = Tk()
textButton = Frame(top)
textButton.pack()
img = PhotoImage(file="bk.gif")
img = img.subsample(1, 1)
background = Label(top, image = img, bd=0)
background.pack()
background.image = img
name_label = Label(textButton, text="Username")
name_label.grid(row=1, sticky=W)
name_entry = Entry(textButton)## the Entry will let the user entre text inside the text box
name_entry.grid(row=1, column=1)
password_label = Label(textButton, text="Password")
password_label.grid(row=2, sticky=W)
password_entry = Entry(textButton, show="*")
password_entry.grid(row=2, column=1)
top.mainloop
You can use place to use an image as a background for other widgets. place doesn't affect the geometry of other widgets so you can use it with grid or pack.
The main think to keep in mind is that you should do this before creating other widgets so that it is lowest in the stacking order. That, or be sure to call lower on it, otherwise it will overlay the other widgets rather than underlay them.
With your code, just remove background.pack() and replace it with these two lines:
background.place(relx=.5, rely=.5, anchor="center")
background.lower()
You don't need to change anything else. The above centers the image. If you instead want the image to start in the upper-left corner you can do it like this:
background.place(x=0, y=0, anchor="nw")
You have to use background as parent for widgets to put them inside Label with background.
I remove Frame to make it simpler. And now I can use weight to automatically resize empty rows and columns around widgets so they will be in the center.
import tkinter as tk
top = tk.Tk()
top.geometry('250x250')
img = tk.PhotoImage(file="hal_9000.gif")
img = img.subsample(1, 1)
background = tk.Label(top, image=img, bd=0)
background.pack(fill='both', expand=True)
background.image = img
# resize empty rows, columns to put other elements in center
background.rowconfigure(0, weight=100)
background.rowconfigure(3, weight=100)
background.columnconfigure(0, weight=100)
background.columnconfigure(3, weight=100)
name_label = tk.Label(background, text="Username")
name_label.grid(row=1, column=1, sticky='news')
name_entry = tk.Entry(background)## the Entry will let the user entre text inside the text box
name_entry.grid(row=1, column=2)
password_label = tk.Label(background, text="Password")
password_label.grid(row=2, column=1, sticky='news')
password_entry = tk.Entry(background, show="*")
password_entry.grid(row=2, column=2)
top.mainloop()
Result:
As you see widgets have gray background which you can't remove. If you need text without gray background then you have to use Canvas with create_text() (and create_window() to put Entry)
Gif file (with HAL 9000) to test code:

Resources