I've looked through several similar questions, but nothing is working. I have a Tkinter program that will open a second window when pressing a button. All of the images in the first window work great, but when I open the second window, I get the folling error message when I to to make a button with images:
_tkinter.TclError: image "pyimage5" doesn't exist
The images are defined and stored like this:
add_icon = PhotoImage(file = 'data/add_icon.gif'), subtract_icon = PhotoImage(file = 'data/subtract_icon.gif')
And they are called like this:
Button(edit, image = add_icon, command = add_new_pref, relief = FLAT) .grid(row = 2, column = 0, sticky = NSEW) Button(edit, image = subtract_icon, command = remove_pref, relief = FLAT) .grid(row = 3, column = 0, sticky = NSEW)
The images are defined after the creation of the new window. Any ideas?
Thanks to TheLizzard for their comment:
Change PhotoImage(file='data/add_icon.gif') to PhotoImage(file="data/add_icon.gif", master=edit)
I guess that the "MASTER" parameter will shift the image's main instance to the specified window.
Related
self.root.after(1000, self.label4.grid(row = 1, column = 0))
self.label3.grid(row = 0, column = 0)
self.label4 = Label(self.frame2, text = "")
self.saveButton = Button(self.frame2, text = "Save")
self.saveButton.grid(row = 20, column = 0)
I am using this line of code to display a Label after 1 second on a frame in tkinter. It has worked with .pack but not with .grid. I want a save button to appear underneath the label but the label to appear above it, hence why I am using the grid system. Here is what I'm getting:
Does anyone know how to fix this?
Thanks.
I am helping with a small project where we want to add and take items away from a store. The code is below:
from tkinter import *
import tkinter
####################
# Variables
eggs = 0
milk = 0
butter = 0
lemon = 0
guiSize = "800x1280"
def newItemGUI():
main.withdraw()
def addEgg():
global eggs
eggs += 1
updateLabels()
def menu():
global eggs
update(eggs)
itemWindow.destroy()
main.deiconify()
def updateLabels():
eggLabel = Label(itemWindow, text = eggs)
eggLabel.grid(row = 3,column = 0)
itemWindow = Toplevel()
itemWindow.geometry(guiSize)
itemWindow.title("Add a new item")
itemWindow.configure(background = "#a1dbcd")
heading = Label(itemWindow, text="Add new items", font=("Arial",20),background = "#a1dbcd")
heading.grid(row=0, columnspan = 3)
egg = PhotoImage(file ="images/egg.gif")
eggButton = Button(itemWindow, image = egg, command = addEgg)
eggButton.grid(row = 2, column = 0,padx = 10, pady = 10)
eggLabel = Label(itemWindow, text = eggs).grid(row = 3,column = 0)
back = Button(itemWindow, text = "Main Menu", command = menu, width = 15)
back.grid(row = 4, column = 0, padx = 20, pady = 20)
def update(eggs):
items.delete("1.0",END)
items.insert(END,"Eggs \t:")
items.insert(END,eggs)
items.insert(END,"\n")
main=tkinter.Tk()
main.geometry(guiSize)
bgColour = "#DDA0DD"
main.configure(background = bgColour)
button1 = Button(main, text="Input new products", width = 20, height = 5, command = newItemGUI)
button1.grid(column = 1, row =2, padx = 20, pady = 20)
label2 = Label(main,text = "Items in the fridge :", font =("Arial,20"), background = bgColour)
label2.grid(row=4, columnspan = 2)
items = Text(main, width = 60, height = 10)
items.insert(END,"Eggs \t:")
items.insert(END,eggs)
items.insert(END,"\n")
items.grid(row=5, columnspan = 4)
main.mainloop()
When you click on the input new products button, this takes you to a new screen. On the screen should be a photo of an egg with a count underneath. For some reason the image of the egg is not showing and the button will not click.
If I change the eggButton from an image to:
eggButton = Button(itemWindow, text = "egg", command = addEgg)
this seems to allow me to click and the variable and it increases. Any idea as to what/where we have gone wrong? I know the path is correct as I can get the button to display a picture of an egg in a Label.
The problem is because the PhotoImage is being stored in a variable named egg which is local to the newItemGUI() function, so it (and associated image object) are being deleted when the function returns. This is a fairly common problem, so your question is likely a duplicate of another (and may get closed).
This PhotoImage documentation mentions avoiding this potential issue the way shown below in the Note near the end.
Regardless, to prevent that from happening, you can store the value somewhere else such as in an attribute of the Toplevel window. I would also recommend changing its name to something more descriptive like egg_image.
Here are changes to your code showing what how it could be done:
itemWindow.egg_image = PhotoImage(file="images/egg.gif")
eggButton = Button(itemWindow, image=itemWindow.egg_image, command = addEgg)
I am creating a GUI with a ".grid" of buttons. And I want to make each of those buttons display a different image on press. So when I click button 1, it will bring up "image1", on the bottom of the buttons. When I click button 2, it will bring up "image2" and etc.
Through some research, I was able to make the buttons run a function that takes in a parameter through the method below. However, I can't seem to make the button display the image. rather, it just makes an empty white space underneath the buttons, when I press any buttons.
Disclaimer:
- I do not want there to be loads of images, there will only be 1 image, and it will change depending on what button i press.
Here's the code:
from tkinter import *
def funct(numimg):
image = PhotoImage(file="image"+str(numimg)+".png")
label = Label(image=image)
label.grid(row = row_no+1, column = 0, columnspan = num_of_cols)
def make_funct(number):
return (lambda: funct(number))
root= Tk()
row_no = -1
buttons = []
num_of_cols = 3
root.resizable(0, 0)
numfiles = 6
for x in range(0, numfiles):
if(x % num_of_cols is 0):
row_no+=1
buttons.append(Button(root, text = "Button "+str(x), bg = '#4098D3', width = 30,height = 13,command = make_funct(x)))
buttons[x].grid(row = row_no, column = x % num_of_cols)
root.mainloop()
So my question is, how do you make each individual button, display a different image when it is pressed? this program right here just leaves an empty white space in replace of the image, and the image is not shown.
There are two major problems with the code you posted.
The first is basically the same as in this question: Why does Tkinter image not show up if created in a function?. You should keep a reference to the PhotoImage object, else it will be garbage collected and it will not show.
The second is that you create a new Label on every button click. You should only make one Label and change the image with the label.config() method.
I would (without wrapping your GUI in a class, which might be a nicer solution) load all images on initialization, save them in a list as attribute of the label and only change the image upon a button click.
I also removed your make_funct function and replaced it with a lambda, which is the most used way to pass variables to a function on callback.
from tkinter import *
def funct(numimg):
label.config(image=label.images[numimg])
root= Tk()
row_no = -1
buttons = []
num_of_cols = 3
root.resizable(0, 0)
numfiles = 3
for x in range(0, numfiles):
if(x % num_of_cols is 0):
row_no+=1
buttons.append(Button(root, text = "Button "+str(x), bg = '#4098D3', width = 30,height = 13, command = lambda n=x: funct(n)))
buttons[x].grid(row = row_no, column = x % num_of_cols)
label = Label(root)
label.grid(row = row_no+1, column = 0, columnspan = num_of_cols)
label.images=[]
for x in range(0, numfiles):
label.images.append(PhotoImage(file="image"+str(x)+".png"))
root.mainloop()
So, here's the deal, i have designed a menu (main) in python using the tkinter module, and what I want is that when I click on a button on the main menu, it opens up another menu (slave), but inside the same window the main menu was. (there is an "Return to main menu" button in the slave menu, so I would like to get back to the main menu if I click this button)
Now, when I click a button, it opens up a new window containing the selected menu...
this is my code so far
from Tkinter import *
def cars ():
cars = Tk ()
Label (cars, text = "Cars Menu").grid (row = 0, columnspan = 2, pady = 20)
Button (cars, text = "Car list", width = 50).grid (row = 1)
Button (cars, text = "New car", width = 50).grid (row = 2)
Button (cars, text = "Erase car", width = 50).grid (row = 3)
Button (cars, text = "Return to main menu", width = 50).grid (row = 4, pady = 20)
root = Tk ()
Label (root, text = "Main Menu").grid (row = 0, columnspan = 2, pady = 20)
Button (root, text = "Cars", width = 30, command = cars).grid (row = 1, column = 0)
Button (root, text = "Bikes", width = 30).grid (row = 1, column = 1)
root.mainloop ()
I'm not sure if I inderstand u correctly : you have main menu with options,and when you click on some option,you want to remove main menu and show another one on its place.I had a similar problem and I think this could help you:
I have the following function:
def _switch_major_panel(self, panel_to_switch_with):
self.major_panel.grid_remove()
self.major_panel = panel_to_switch_with
self.major_panel.grid(sticky='nwes')
self.update()
: here self is Frame object,so is major_panel.major_panel is an attribute to my class Application.Your's may be something like current_menu or something like that.
What I do is this: every time I want to change what my content of major_panel is I create a new Frame with the new content and simply use this function to replace the old one.Try that.
I'm far from an expert but that worked for me.
Good luck
I'm new to this GUI business with python2.7 and Tkinter. I'm trying to create a new frame depending on which Radiobutton the user choose, like a menu. When I click on a radiobutton it creats a new frame just like I want, but if I continue to click on the same radiobutton, it will create another frame, and another frame, etc. Can't seem to figure out on how to check if the Radiobutton is already marked (clicked on just once).
Hope I made myself clear, thankful for help!
class Books:
""" Books() is the main class for creating the whole interface """
def __init__(self):
""" Initialize the first function in class Books() """
self.library = "library.txt"
self.filepath = os.getcwd() + "/" + self.library
self.window = Tk()
self.window.title("Personal library")
self.window.wm_iconbitmap(default="myicon.ico")
userChoice = Frame(self.window, height = 1, bd = 1, relief = RIDGE)
userChoice.pack(side = TOP, pady = 10, padx = 5)
self.menuChoice = IntVar()
btAddBooks = Radiobutton(userChoice, text = "Add a new book to the library", value = 1, variable = self.menuChoice, command = self.processChoice)
btAddBooks.grid(row = 1, sticky = W)
btFindBooks = Radiobutton(userChoice, text = "Print info about a book", value = 2, variable = self.menuChoice, command = self.processChoice)
btFindBooks.grid(row = 2, sticky = W)
btPrintBooks = Radiobutton(userChoice, text = "Print all book titles in library", value = 3, variable = self.menuChoice, command = self.processChoice)
btPrintBooks.grid(row = 3, sticky = W
def processChoice(self):
""" Used to handle user choice of Radiobuttons """
if self.menuChoice.get() == 1:
self.processAddBooks()
elif self.menuChoice.get() == 2:
self.processFindBook()
elif self.menuChoice.get() == 3:
self.processShowBooks(self.filepath)
def processAddBooks(self):
""" Add a new book to the library. """
# Create a new frame
questions = Frame(self.window, height = 1, bd = 1, relief = SUNKEN)
questions.pack(fill = X, pady = 10, padx = 5)
# Do stuff with frame here...
Well, if you only need one frame to be open at a time, you can call frame.destroy() on the previous frame before you instantiate the new frame. However, this approach will require that there be something initialized for Tkinter to destroy the first time one of the buttons is selected, otherwise you'll get an error. For my purpose, I just created a throwaway class with a destroy method that did nothing, then used an instance of that class as a placeholder bound to that variable until my Toplevel widget was created for the first time. If you want multiple frames open at the same time, just not duplicates of the same option, try using a different variable name for each frame and only creating the frame if not frame.winfo_exists()--though I'm not 100% sure this wouldn't be susceptible to the same issue of needing a placeholder assigned to that variable until the frame is created the first time. If such is needed, the placeholder class would need a winfo_exists() method that would return False.