When trying to place an image in a button, I get an error "_tkinter.TclError: image "pyimage1" doesn't exist". The image does exist though because I used it on another button and it works there.
When I try to use the image again on a second button that's when the error occurs.
I have tried removing the image and the button works. Tried using the image on anther button and it works for one button only.
from tkinter import ttk
from tkinter import Tk, PhotoImage
class Window(Tk):
def __init__(self, *args, **kwargs):
Tk.__init__(self, *args, **kwargs)
def main():
root = Tk()
style = ttk.Style(root)
style.theme_use('clam')
root2 = Tk()
style = ttk.Style(root2)
style.theme_use('alt')
root3 = Tk()
style = ttk.Style(root3)
style.theme_use('classic')
root4 = Window()
style = ttk.Style(root4)
style.theme_use('default')
icon = PhotoImage(file='test.gif')
# This line works, the image appears on the button.
ttk.Button(root, image=icon, compound='left', text="Quit", command=root.destroy).pack()
# This line works with out the image.
ttk.Button(root2, compound='left', text="Quit", command=root2.destroy).pack()
# This line does not work with an image.
# if the line below is un-commented the code does not work, the error I get is below.
# _tkinter.TclError: image "pyimage1" doesn't exist
# ttk.Button(root2, image=icon, compound='left', text="Quit", command=root2.destroy).pack()
ttk.Button(root3, text="Quit", command=root3.destroy).pack()
ttk.Button(root4, text="Quit", command=root4.destroy).pack()
root.mainloop()
if __name__ == '__main__':
main()
I want images on all buttons.
I can only get it to work for one button only.
You're going to have to create another PhotoImage for each window with the master keyword:
icon = PhotoImage(master=root, file='test.gif')
icon2 = PhotoImage(master=root2, file='test.gif')
icon3 = PhotoImage(master=root3, file='test.gif')
icon4 = PhotoImage(master=root4, file='test.gif')
And then use each icon for the corresponding button:
ttk.Button(root, image=icon, compound='left', text='Quit', command=root.destroy).pack()
ttk.Button(root2, image=icon2, text='Quit', command=root2.destroy).pack()
ttk.Button(root3, image=icon3, text='Quit', command=root3.destroy).pack()
ttk.Button(root4, image=icon4, text='Quit', command=root4.destroy).pack()
Hope this works for you.
Related
I'm building an app that's supposed to display various images from a local folder depending on which button is clicked in the app.
So far, I have started out with an example I've found and try to modify it, but I can't figure out how to summon a .jpg or .png via a button click in the first place. Here's my very basic code so far:
import tkinter as tk
def write_slogan():
print("Tkinter is easy to use!")
root = tk.Tk()
frame = tk.Frame(root)
frame.pack()
button = tk.Button(frame,
text="QUIT",
fg="red",
command=quit)
button.pack(side=tk.LEFT)
slogan = tk.Button(frame,
text="Hello",
command=write_slogan)
slogan.pack(side=tk.LEFT)
root.mainloop()
Essentially, instead of writing the slogan in the console, I would like the button click to trigger an image being displayed. How would I go about achieving that?
I have amended your code so when you click your button the image "test.png" will display on a label.
Here is the code for testing, in my case "test.png" was in the same directory as my Python script.
import tkinter as tk
render = None
def write_slogan():
# get image and display
image = tk.PhotoImage(file = "test.png")
imageLabel.configure(image = image)
imageLabel.image = image
root = tk.Tk()
frame = tk.Frame(root)
frame.pack()
button = tk.Button(frame,
text="QUIT",
fg="red",
command=quit)
button.pack(side=tk.LEFT)
slogan = tk.Button(frame,
text="Hello",
command=write_slogan)
slogan.pack(side=tk.LEFT)
imageLabel = tk.Label(frame)
imageLabel.pack(side=tk.LEFT)
root.mainloop()
Also, this thread was helpful.
You can pass the image filename to the function, so that different buttons show different images:
import tkinter as tk
from PIL import ImageTk
def show_image(imagefile):
image = ImageTk.PhotoImage(file=imagefile)
imagebox.config(image=image)
imagebox.image = image # save a reference of the image to avoid garbage collection
root = tk.Tk()
frame = tk.Frame(root)
frame.pack()
button = tk.Button(frame, text="QUIT", fg="red", command=quit)
button.pack(side=tk.LEFT)
slogan = tk.Button(frame, text="Hello", command=lambda: show_image("slogan.png"))
slogan.pack(side=tk.LEFT)
other = tk.Button(frame, text="World", command=lambda: show_image("other.jpg"))
other.pack(side=tk.LEFT)
# label to show the image
imagebox = tk.Label(root)
imagebox.pack()
root.mainloop()
Since tk.PhotoImage() does not support JPG image, external Pillow module is used instead.
I think most of us must have seen the command prompt(windows) and how when we open it and click on it's icon and it shows a menu. Can we do a similar thing with tkinter? This is not the normal menubar.
Here is an illustration of the command prompt one.
This is just an exampel of a work around without the need of doing all your window management by your own. Of course it will need improvements but as a start: Popup stolen from
import tkinter as tk
from PIL import Image, ImageTk
def popup(event):
popup_menu.tk_popup(event.x_root, event.y_root, 0)
def set_icon():
global top, popup
top = tk.Toplevel(root)
top.overrideredirect(1)
top.attributes('-topmost',True)
offset = 30
x,y = root.winfo_rootx(),root.winfo_rooty()-offset
width, height = offset,offset
top.geometry("%dx%d+%d+%d" % (width,height, x,y))
my_label = tk.Label(top, image=photo)
my_label.pack(fill='both')
global popup_menu
popup_menu = tk.Menu(top, tearoff=0)
popup_menu.add_command(label="Delete",
command=lambda :print('del'))
popup_menu.add_command(label="Select All",
command=lambda :print('sel'))
top.bind("<Button-1>", popup)
def grab(event):
top.geometry(f'+{event.x+10}+{event.y+2}')
root=tk.Tk()
ico = Image.open('prac_img/p2.png')
photo = ImageTk.PhotoImage(ico)
root.iconphoto(False,photo)
#root.wm_iconphoto(False,photo)
root.bind('<Configure>',grab)
root.update_idletasks()
set_icon()
root.mainloop()
Another way would be to code your own titlebar and the use of overrideredirecr(1) which will undecorate your window by the window manager of your system.
topper = Toplevel()
topper.title("2nd Window")
topper.state('zoomed')
my_img = ImageTk.PhotoImage(Image.open("diamond.png"))
my_label = Label(topper, image=my_img, height = 100 , width = 100)
F21 = Frame(topper, borderwidth=83, bg="blue", relief=SUNKEN)
button1 = Button(topper, text="class", command=topper.destroy)
button1.pack()
my_label.pack()
I am running the code and I get no errors, button is working as well but I'm not able to see the picture in the window.
Welcome to Stackoverflow Shakti!
For the future - it is always good to supply a Minimal, Reproducible Example so others can replicate and understand your issue better in order to help you! It also helps you to understand where exactly the error originates.
When you call Toplevel() from another tkinter window to open a new window, you will need to call "mainloop()" on the second window as well in order to display an image - try my code with an example image and comment/uncomment the line with
topper.mainloop()
to see the difference in functionality.
The adapted code:
from tkinter import *
from PIL import Image, ImageTk # pip install pillow
def show_second_window():
topper = Toplevel()
topper.title("2nd Window")
topper.state('zoomed')
my_img = ImageTk.PhotoImage(Image.open("t1.png"))
my_label = Label(topper, image=my_img, height=100, width=100)
F21 = Frame(topper, borderwidth=83, bg="blue", relief=SUNKEN)
button1 = Button(topper, text="class", command=topper.destroy)
button1.pack()
my_label.pack()
topper.mainloop() # <---- this is needed to show the image!
root = Tk()
root.title("1st window")
button = Button(root, text="show second window", command=show_second_window)
button.pack()
root.mainloop()
I am developing a GUI on Python and I have the following problem: I want to have the picture at the top of the window and buttons right underneath it. I am using the Tkinter module and whatever geometry I use (place, pack or grid) the buttons don't move. The are only displayed if I move the image using grid to row 1 (which is the second row), otherwise they don't appear at all. Here is the code I am using for now. For reference the picture has dimensions of 291x87 pixels.
import Tkinter
from Tkinter import *
def main():
window =Tk()
window.geometry("300x300")
window.title("Dienes Blocks Application")
window.iconbitmap(default='favicon.ico')
app = HomeScreen(window)
window.mainloop()
class HomeScreen(Frame):
def __init__(self, master):
Frame.__init__(self,master)
self.create_buttons()
self.sparx_head()
def sparx_head(self):
self.grid()
photo = Tkinter.PhotoImage(file="logosmall.gif")
sparx_header = Label(image=photo)
sparx_header.image = photo # keep a reference!
sparx_header.grid(column=0, row=0, columnspan=2, rowspan=2, sticky='NSEW')
def create_buttons(self):
self.grid()
#teacher button
teacher_button = Tkinter.Button(self, text="Teacher")
teacher_button.grid(column=0, row=10)
# student button
student_button = Tkinter.Button(self, text="Student")
student_button.grid(column=2, row=10)
# prototype button
prototype_button = Tkinter.Button(self, text="Prototype")
prototype_button.grid(column=1, row=10)
if __name__ == "__main__":
main()
You just need to use self in the image label:
sparx_header = Label(self,image=photo)
They were not having the same parent & that's why you were having this problem
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')