I'm learning Tkinter and I'm a bit confused.
The code below is showing the white text from the face_recogniton() function.
import tkinter as tk
from PIL import Image, ImageTk
from facerec_on_raspberry_pi import face_function #face_function() return recognized person name
root = tk.Tk()
#Fullscreen
root.overrideredirect(True)
root.overrideredirect(False)
root.attributes('-fullscreen',True)
root.configure(background='black')
def my_mainloop():
print (face_function())
instructions = tk.Label(root, text=str(face_function()), font=('Raleway', 55), fg='white', bg='black')
instructions.place(x=160, y=60)
root.after(1, my_mainloop)
root.after(1, my_mainloop)
root.mainloop()
But the text is overlaying. How can I clean it before showing new text?
Here are the images of what's happening:
Here is Unknown Person and Barack Obama overlaying -
Here is None and Unknown Person overlaying.
You don't need to re-create your label every time you need to change text. The text of existing label can be changed after creation. Also note the two lines I commented: you don't need both.
import tkinter as tk
from PIL import Image, ImageTk
from facerec_on_raspberry_pi import face_function #face_function() return recognized person name
root = tk.Tk()
#Fullscreen
root.overrideredirect(True) # Use only one of this two lines:
root.overrideredirect(False) # you just set a flag and then change it
root.attributes('-fullscreen',True)
root.configure(background='black')
instructions = tk.Label(root, text='', font=('Raleway', 55), fg='white', bg='black')
instructions.place(x=160, y=60)
def my_mainloop():
print (face_function())
instructions['text'] = str(face_function())
root.after(1, my_mainloop)
root.after(1, my_mainloop)
root.mainloop()
Related
How do I use user input to retrieve an image, and display it on the screen? I have the user input field in Tkinter, and I do not know how to get that to go to my folder, and get the image to show up on the same screen.
EDIT: I was able to get the path to show on the screen, but now I don't know how to get the actual image to show up from that path inside the frame... I do not know how to link this path to have the program display the image, i.e. myimage1 from my folder.
from tkinter import *
from PIL import ImageTk,Image
from tkinter import ttk
from tkinter import filedialog
root = Tk()
root.title("Images")
root.iconbitmap(r'C:\Users\hadhikari\example\Takumi_Logo.ico')
button_quit = Button(root, text= "Exit Program", command=root.quit)
button_quit.pack()
e= Entry(root, width=50, bg="light blue", borderwidth=3)
e.pack()
e.insert(0," ")
def myClick():
link = "r'C:\\Users\\hadhikari\\example\\" + e.get()
myLabel1 = Label(root, text=link)
myLabel1.pack()
myButton = Button(root, text="Scan Part Number", command=myClick,
bg="pink", fg="white")
myButton.pack()
#my_img = ImageTk.PhotoImage(Image.open('link'))
#my_Label = Label(image=my_img)
#my_Label.pack()
#def getText():
# inputtedtext = entrybox.get()
#entrybox = Entry(root)
#entrybox.pack()
#btn = Button(root, text="Submit", command=getText)
#btn.pack()
frame = LabelFrame(root, padx=100, pady=100)
frame.pack(padx=50, pady=50)
root.mainloop()
As suggested in the comments, maybe using Tkinter's askopenfilename dialog might be a better choice than hardcoding the filepath, and letting the user input the filename.
But, first of all, let's fix the code following your intentions. Most of the part on how to properly set up a Tkinter Label, and dynamically place images in that, can be easily found, for example in this Q&A. Basically, you want to put the "update routine" inside your myClick method:
from tkinter import *
from PIL import Image, ImageTk
# How to properly set up Tkinter label with dynamically changeable
# ImageTk.PhotoImage: https://stackoverflow.com/a/3482156/11089932
root = Tk()
button_quit = Button(root, text='Exit Program', command=root.quit)
button_quit.pack()
e = Entry(root, width=50, bg='light blue', borderwidth=3)
e.pack()
e.insert(0, '')
my_label = Label()
my_label.pack()
def myClick():
link = r'your/path/goes/here' + e.get()
my_img = ImageTk.PhotoImage(Image.open(link))
my_label.configure(image=my_img)
my_label.image = my_img
myButton = Button(root, text='Scan Part Number', command=myClick,
bg='pink', fg='white')
myButton.pack()
root.mainloop()
Program at startup:
Opening the first image:
Opening another image:
Now, regarding the askopenfilename dialog, we get rid of the Entry widget, and simply open the dialog inside the myClick method:
from tkinter import *
from tkinter.filedialog import askopenfilename
from PIL import Image, ImageTk
# How to properly set up Tkinter label with dynamically changeable
# ImageTk.PhotoImage: https://stackoverflow.com/a/3482156/11089932
root = Tk()
button_quit = Button(root, text='Exit Program', command=root.quit)
button_quit.pack()
my_label = Label()
my_label.pack()
def myClick():
link = askopenfilename()
my_img = ImageTk.PhotoImage(Image.open(link))
my_label.configure(image=my_img)
my_label.image = my_img
myButton = Button(root, text='Scan Part Number', command=myClick,
bg='pink', fg='white')
myButton.pack()
root.mainloop()
Program at startup:
Opening the first image (dialog):
Opening the first image (display):
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.19041-SP0
Python: 3.9.1
PyCharm: 2021.1.3
Pillow: 8.3.1
----------------------------------------
I am trying to bind a photo to the list box, but the photo does not appear.
I tried to take a specific photo path here. with the same code above (in the choosePhoto) and it worked. For some reason when in the code inside the function and is binding the function to the listBox, the photo does not appear.
My code:
from tkinter import *
from PIL import ImageTk, Image
from os import *
def openPath(path,listBox):
try:
path2=str(path)
list1= listdir(path2)
listBox.delete(0,END)
for i in range(len(list1)):
listBox.insert(i,list1[i])
except:
print("file does not exist")
def choosePhoto(event):
path=str(textFolder.get())+"\\"+str(listBoxPath.get(ACTIVE))
image1=ImageTk.PhotoImage(Image.open(path))
lbl.configure(image=image1)
print(path)
root = Tk()
root.geometry("450x600")
root.title("project image proccesor")
frame1=Frame(root,width=250,height=100)
frame1.pack(side=LEFT,fill=BOTH)
frame4=Frame(root,width=250,height=100)
frame4.pack(side=RIGHT,fill=BOTH)
lblFolder=Label(frame1,text="Enter folder path:")
lblFolder.grid(row=0,column=0)
textFolder=Entry(frame1,insertwidth=4)
textFolder.grid(rowspan=1,column=0)
listBoxPath=Listbox(frame1)
listBoxPath.grid(row=2)
bChoose=Button(frame1,text="Choose",command=lambda: openPath(textFolder.get(),listBoxPath)).grid(row=1,column=1)
lbl=Label(frame4, text="waiting for photo")
listBoxPath.bind('<<ListboxSelect>>', choosePhoto)
root.mainloop()
There are 3 issues I can see here in your code.
1st. You need to define image1 as a global because this image is currently a local variable in the function and once the function completes the images is deleted unless you define it in the global namespace.
2nd. Your label that is used for displaying the images has not yet been placed on the screen. You need to use some geometry manager (probably grid()) in this case to display the image.
3rd. You are currently using ACTIVE in your selection on the list box. This will results in you selecting what was active prior to you clicking instead of what you just clicked on.
Change this:
list_box_path.get(ACTIVE)
to this:
list_box_path.get(list_box_path.curselection())
I have cleaned up your code a bit to more closely fit the PEP8 standard and added some minor changes and reduced section of code that were not needed.
import tkinter as tk
from PIL import ImageTk, Image
from os import listdir
def open_path(path):
try:
list1 = listdir(path)
list_box_path.delete(0, "end")
for i in range(len(list1)):
list_box_path.insert(i, list1[i])
except:
print("file does not exist")
def choose_photo(event):
global image1
path = Image.open("{}\\{}".format(text_folder.get(), list_box_path.get(list_box_path.curselection())))
image1 = ImageTk.PhotoImage(path)
lbl.configure(image=image1)
root = tk.Tk()
root.geometry("450x600")
root.title("project image processor")
frame1 = tk.Frame(root, width=250, height=100)
frame4 = tk.Frame(root, width=250, height=100)
lbl_folder = tk.Label(frame1, text="Enter folder path:")
text_folder = tk.Entry(frame1, insertwidth=4)
list_box_path = tk.Listbox(frame1)
b_choose = tk.Button(frame1, text="Choose", command=lambda: open_path(text_folder.get()))
lbl = tk.Label(frame4, text="waiting for photo")
frame1.pack(side="left", fill="both")
frame4.pack(side="right", fill="both")
lbl_folder.grid(row=0, column=0)
text_folder.grid(rowspan=1, column=0)
list_box_path.grid(row=2)
b_choose.grid(row=1, column=1)
lbl.grid(row=0, column=0)
list_box_path.bind('<<ListboxSelect>>', choose_photo)
root.mainloop()
I am trying to add an image to a button, but I have got some issues when I try to execute the current code. All it shows is an image with no words. I can't even see the button either. Is there some way of fixing my current code?
from tkinter import *
import tkinter as tk
root = tk.Tk()
root.geometry("960x600")
canvas = Canvas(root, width=500, height=500)
canvas.pack()
imagetest = PhotoImage(file="giftest.gif")
canvas.create_image(250, 250, image=imagetest)
button_qwer = Button(root, text="asdfasdf", image=imagetest)
root.mainloop()
You need to pack (or grid) your button in the window, here is how you could do:
import tkinter as tk
from tkinter import PhotoImage
def print_hello():
print('hello')
root = tk.Tk()
root.geometry("960x600")
imagetest = PhotoImage(file="giftest.gif")
button_qwer = tk.Button(root, text="asdfasdf", image=imagetest, command=print_hello)
button_qwer.pack() # <-- don't forget to place the button in the window
root.mainloop()
You can have both text and image displayed on your button, using the compound option, like this:
button_qwer = tk.Button(root, image=imagetest, text="asdfasdf", compound="top", command=print_hello)
compound options are bottom, center, left, none, right, or top
You are making the button successfully but you are not drawing it onto the screen/interface. Use pack , place or grid.
button_qwer = Button(root, text="asdfasdf", image=imagetest)
button_qwer.pack()
Your full code can be like:
from tkinter import *
import tkinter as tk
root = tk.Tk()
root.geometry("960x600")
canvas = Canvas(root, width=500, height=500)
canvas.pack()
imagetest = PhotoImage(file="giftest.gif")
canvas.create_image(250, 250, image=imagetest)
button_qwer = Button(root, text="asdfasdf", image=imagetest)
button_qwer.pack()
root.mainloop()
I would like for a cant afford label to appear then after a second disappear when i push a button to buy something. It seems like the time.sleep(1) is making it not work properly. This is done on python tkinter.
def buttonpressed():
Label.place(x = 500, y = 500 #where i want the label to appear
time.sleep(1)
Label.place(x = 10000, y = 10000) #moving it away where i wont be able to see it
You can't use sleep because it stops mainloop
You can use root.after(time_in_milliseconds, function_name) to run function
Example
import tkinter as tk
def button_pressed():
# put text
label['text'] = "Hello World!"
# run clear_label after 2000ms (2s)
root.after(2000, clear_label)
def clear_label():
# remove text
label['text'] = ""
root = tk.Tk()
label = tk.Label(root) # empty label for text
label.pack()
button = tk.Button(root, text="Press Button", command=button_pressed)
button.pack()
root.mainloop()
If you have to create and remove label then use label.destroy()
import tkinter as tk
def button_pressed():
label = tk.Label(root, text="Hello World!")
label.pack()
root.after(2000, destroy_widget, label) # label as argument for destroy_widget
def destroy_widget(widget):
widget.destroy()
root = tk.Tk()
button = tk.Button(root, text="Press Button", command=button_pressed)
button.pack()
root.mainloop()
And shorter version without destroy_widget
import tkinter as tk
def button_pressed():
label = tk.Label(root, text="Hello World!")
label.pack()
root.after(2000, label.destroy)
root = tk.Tk()
button = tk.Button(root, text="Press Button", command=button_pressed)
button.pack()
root.mainloop()
Press button many times to see many labels which disappear after 2s.
You can use after() to set up a callback after a specified interval. In the callback function clear the label with pack_forget() (or grid_forget() if you're using grid). This is better than setting the label's text attribute to an empty string because that causes widgets to be resized, which might not be what you want. Here's an example:
import Tkinter as tk
class App():
def __init__(self):
self.root = tk.Tk()
self.label = tk.Label(text='I am a label')
self.label.place(x=0, y=0)
self.label.after(1000, self.clear_label) # 1000ms
self.root.mainloop()
def clear_label(self):
print "clear_label"
self.label.place_forget()
app=App()
Another option is to use self.label.destroy() to destroy the widget, however, pack_forget() allows you to display the label again by calling pack() on the widget again.
# I made it through calling 2 functions:
from tkinter import *
root = Tk()
root.geometry('400x200') # width by height
def one_text():
label['text'] = "Look around"
root.after(1000, another_text)
def another_text():
label['text'] = "and smile"
root.after(1000, one_text)
label= Label(root ,font=('Helvetica', 14), fg='black', bg='white')
label.pack()
one_text()
root.mainloop()
I am trying to display an image in python using the tkinter canvas option. However, if I input it in a class, like below, it doesn't give an error but also doesn't show my image. The buttons are displayed correctly though. Also, if I take the code for generating this image out of the class it works correctly. I can't seem to find out what the problem is.
import Tkinter as tk
from Tkinter import *
class Board(tk.Frame):
def __init__(self,parent):
frame = Frame(parent)
frame.pack()
tk.Frame.__init__(self,parent)
frame2 = Frame(frame)
frame2.pack()
c=Canvas(frame2)
c.pack(expand=YES,fill=BOTH)
background=PhotoImage(file='Board.gif')
c.create_image(100,100,image=background,anchor='nw')
button = Button(frame, text="Next turn", command=self.next_turn)
button.pack()
button = Button(frame, text="Roll the dice", command=self.roll)
button.pack()
....
root = Tk()
board = Board(root)
board.pack()
root.mainloop()
You have to keep a reference to the PhotoImage. This is just and example (you can also use self.background instead of c.background):
c = Canvas(frame2)
c.pack(expand=YES,fill=BOTH)
c.background = PhotoImage(file='Board.gif')
c.create_image(100,100,image=c.background,anchor='nw')