I'm trying to create a python program tkinter that, upon the pressing of a button, opens a new full screen tkinter window containing an image and plays an audio file - here's my code:
from tkinter import *
from PIL import Image, ImageTk
from playsound import playsound
def play():
window = Toplevel()
window.attributes('-fullscreen', True)
img = ImageTk.PhotoImage(Image.open("pic.png"))
label = Label(window, image=img).pack()
playsound("song.mp3")
buttonWindow = Tk()
b = Button(buttonWindow, text="Press Button", command=play)
b.pack()
(my image and audio file are both on the desktop with my python file)
However, when I run my code, when I press the button, the audio plays but no second tkinter window opens.
I've tried to destroy() the buttonWindow and have tried many different ways of including an image on a tkinter window - if I remove the line of code using PhotoImage(), the window appears (obviously I then get a syntax error stating that 'img' is not defined).
How could I solve this?
Thanks,
Louis
I had similar problem.
But i resolve this trial and error method.
First of all i don't use pillow library and put image into Label
You should try define Photoimage object NOT IN FUNCTION
Example:
It will work:
import tkinter as tk
root = tk.Tk()
root.geometry("600x400")
def popUp():
popff = tk.Toplevel(root)
popff.geometry("400x200")
labelImgff = tk.Label(popff, image=imgff, bg="white")
labelImgff.grid(row=0, column=0)
imgff = tk.PhotoImage(file="/home/user/image.png")
btnff = tk.Button(text="startPOP", command=popUp)
btnff.grid(column=0,row=0)
root.mainloop()
effect of action
Your playsound() command is blocking execution. The playsound() command has an optional field 'block', which is True by default. Changing this to False will continue execution and allow mainloop() to continue.
Second, just call label.draw() to draw your image to the TopLevel window.
Here's the code:
from tkinter import *
from PIL import Image, ImageTk
from playsound import playsound
def play():
window = Toplevel()
window.attributes('-fullscreen', True)
img = ImageTk.PhotoImage(Image.open("pic.jpeg"))
label = Label(window, image=img).pack()
playsound("song.mp3",block=False)
label.draw()
buttonWindow = Tk()
b = Button(buttonWindow, text="Press Button", command=play)
b.pack()
buttonWindow.mainloop()
Cheers!
Related
Code Part 1
from tkinter import *
from PIL import Image, ImageTk
import threading
c1 = "#262626"
root = Tk()
root.overrideredirect(True)
root.configure(bg=c1)
def destroy():
global root
root.destroy()
def pr():
print("asd")
destroy()
def animation():
threading.Timer(0.01, pr).start()
animation()
root.mainloop()
after the destroy () command has worked, the window is closed, but the program continues to work, you can disable it only with the help of the task manager or CMD, but there's no any errors.
Code Part 2
login = Tk()
img = Image.open(selfDir + "\\ok.png").resize((50, 50), Image.ANTIALIAS)
test = ImageTk.PhotoImage(img)
label1 = Label(login, image=test, bg=c1)
label1.image = test
label1.place(x=330, y=145, width=50, height=50)
login.mainloop()
if I run this part after the first one, I see an error:
tkinter.TclError: can't invoke "image" command: application has been destroyed
but if I run only this part, without the first one, then it works and I can see the photo in the window
So the problem is.
I need to close window after threading.Timer()
Then i need to open window, with an image
i just need to write
root.after(10, pr)
instead of
threading.Timer(0.01, pr).start()
special thanks to Matiiss
I'm a Python beginner that trying to learn my way through Tkinter, and I need your help.
Let say I create a simple button like this:
import tkinter as tk
window = tk.Tk()
button = tk.Button(text="Hello World!")
button.pack()
window.mainloop()
Is there a way that I can hide and then display the text again? Given that I can create two more buttons that will do the job of hiding and displaying. I have tried to use button.pack_forget(), but it will hide the entire button instead.
Any help would be appreciated.
To make it look like the buttons text vanishes,you can make the text color as same as the background color via cget method.
import tkinter as tk
def hide_text():
color = button['bg']
button.config(foreground=color, activeforeground=color)
window = tk.Tk()
button = tk.Button(text="Hello World!",command=hide_text)
button.pack()
window.mainloop()
Approach 2 ttk.Button:
import tkinter as tk
from tkinter import ttk
def hide_text():
button.config(text='')
window = tk.Tk()
button = ttk.Button(text="Hello World!",width=100,command=hide_text)
button.pack()
window.mainloop()
Approach3 using style:
import tkinter as tk
from tkinter import ttk
def change_button_style(event):
widget = event.widget
if widget['style'] == 'TButton':
widget.configure(style='VanishedText.TButton')
else:
event.widget.config(style='TButton')
BACKGROUND = '#f0f0f0'
FOREGROUND = '#000000'
window = tk.Tk()
window.configure(bg=BACKGROUND)
style = ttk.Style()
style.theme_use('default')
button = ttk.Button(text="Hello World!",style='VanishedText.TButton')
button.bind('<ButtonPress-1>',change_button_style)#,command=change_button_style
button.pack()
style.map('VanishedText.TButton',
foreground =[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)],
background =[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)],
focuscolor=[('disabled',BACKGROUND),
('!disabled',BACKGROUND),
('pressed',BACKGROUND),
('!pressed',BACKGROUND),
('active',BACKGROUND),
('!active',BACKGROUND)])
window.mainloop()
You Can Simply Config And Set Text :
import tkinter as tk
from tkinter import ttk
win=tk.Tk()
def hidetext():
button.config(text="")
button=ttk.Button(win,text="FooBar",command=hidetext)
button.pack()
win.mainloop()
I want to open a new window which includes an image. I don't know how to achieve this. Currently, my code opens up a plain window with a button saying show image.
from tkinter import *
from PIL import ImageTk, Image
root = Tk()
root.configure(background = "black")
obrazek = ImageTk.PhotoImage(Image.open("dn.jpg"))
def click():
MyLabel = Label(root, image = obrazek)
Tk()
MyLabel.pack()
myButton = Button(root, text = "Wyjście", command = click, fg = "white", bg = "#000000")
myButton.pack()
mainloop()
This is minimal working example.
You have to use Tk() only to create main window. For other windows you have to use Toplevel. And when you have it in variable ie. top then you have to use it as first argument in Label (or other widget) to display widget in this window.
BTW: PEP 8 -- Style Guide for Python Code
#from tkinter import * # PEP8: `import *` is not preferred
import tkinter as tk
from PIL import ImageTk, Image
# --- functions ---
def click():
top = tk.Toplevel()
my_label = tk.Label(top, image=my_image)
my_label.pack()
# --- main ---
root = tk.Tk()
#root.configure(background="black") # PEP8: without spaces around `=`
my_image = ImageTk.PhotoImage(Image.open("lenna.png")) # PEP8: english names
my_button = tk.Button(root, text="Wyjście", command=click) # PEP8: lower_case_names for variables
my_button.pack()
root.mainloop()
Image from Wikipedia: Lenna
EDIT:
I hope you didn't create PhotoImage inside function because there is bug in PhotoImage which removes image from memory when it is assigned to local variable in function. And then you can see empty image. It has to be assigned to global variable or to some object - ie. my_label.img = image
i want to make a button that displays a pop up message with a photo in it, but when i click it displays "pyimage1"
from tkinter import messagebox
from tkinter import *
from PIL import ImageTk, Image
def message():
messagebox.showinfo("title", ImageTk.PhotoImage(Image.open(r'C:\Users\EH\Pictures\cat.jpg')))
root = Tk()
root.geometry('700x500')
root.title("cat pic button")
button = Button(root, text="show me cute cat pic", command=message)
button.pack()
root.mainloop()
i did something wrong which was choosing messagebox to display a photo
i solved it by replacing the message function with this:
def message():
global my_img
top = Toplevel()
top.title("cat photo")
my_img = ImageTk.PhotoImage(Image.open(r'C:\Users\EH\Pictures\cat.jpg'))
Label(top, image=my_img).pack()
I've written a bunch of code that produces a GUI. Now whenever I run the code it produces the main GUI window and one additional small window with nothing in it. When I close the smaller window the large main window disappears.
Now I've been reading other posts with similar problems, but I haven't been able to identify where the error is in my code.
Please help :)
Follow up question: How would I add a background image rather than the grey boring color?
Here is what it looks like.
#%% GUI Interface
import Tkinter as tk
from tkFont import Font
from PIL import ImageTk, Image
from Tkinter import END
#This creates the main window of an application
window = tk.Toplevel()
window.title("Sat Track")
window.geometry("1200x800")
window.configure(background='#f0f0f0')
#Imports the pictures.
pic1 = "Globeview.png"
pic2 = "MercatorView.png"
pic3 = "currentweathercroppedsmall.png"
pic4 = "GECurrentcroppedsmall.png"
#Creates a Tkinter-compatible photo image, which can be used everywhere Tkinter expects an image object.
img1 = ImageTk.PhotoImage(Image.open(pic1))
img2 = ImageTk.PhotoImage(Image.open(pic2))
img3 = ImageTk.PhotoImage(Image.open(pic3))
img4 = ImageTk.PhotoImage(Image.open(pic4))
header = tk.Label(window, text="Satellite Control Center", font=Font(size=40))
header.pack()
toprow = tk.Frame(window)
infobox = tk.Text(toprow, width=50, height=7, font=("Calibri",12))
infobox.pack(side = "left")
infobox.insert(END,"Current information for:"+spacer+name +'\n'+
"Time:" +space+times+ '\n'+
"Longitude:"+space +x_long+ '\n'+
"Latitude:" +space+x_lat+ '\n'+
"Altitude:" +space+alt+space+ "[km]"+'\n'+
"Velocity:" +space+vel+space+ "[km/s]" + '\n'+
"Spatial Resolution: "+space +spat+space+ "[Pixels pr. m]"
)
toprow.pack()
midrow = tk.Frame(window)
globeview = tk.Label(midrow, image = img1)
globeview.pack(side = "left") # the side argument sets this to pack in a row rather than a column
mercatorview = tk.Label(midrow, image = img2)
mercatorview.pack(side = "left")
midrow.pack() # pack the toprow frame into the window
bottomrow = tk.Frame(window)
currentweather= tk.Label(bottomrow, image = img3)
currentweather.pack(side = "left")
gearth = tk.Label(bottomrow, image = img4)
gearth.pack(side = "left")
bottomrow.pack()
#Start the GUI
window.mainloop()
Every tkinter application needs exactly one instance of Tk class. In your code you don't create one but mainloop seem to create one automatically it's still created (See Bryan's comment below), even though you can't(easily) refer to it later.
If you will use additional Toplevel widgets to that of your curent one go:
root = tk.Tk()
root.withdraw() # You can go root.iconify(), root.deiconify() later if you
# want to make this window visible again at some point.
# MAIN CODE HERE
root.mainloop()
if not simply replace:
window = tk.Toplevel()
with:
window = tk.Tk()
Note: Also note that if you're working using IDLE keep in mind that it creates its own Tk object which may hide the fact that your application will need one when used standalone.
Remove Toplevel from window = tk.Toplevel(). I don't have a python2 dist available -- I'm on python3 but when I removed TopLevel from my code, it only brought up one window. So, the python3 way is....
import tkinter as tk
#This creates the main window of an application
window = tk.Tk()
#Start the GUI
window.mainloop()
I think the only difference would be that python2's tkinter is actually Tkinter (as you have already done).