Why is my Tkinter image not working? It is in the same directory, all commands are right but I get the error:
_tkinter.TclError: image "pyimage1" doesn't exist.
What's wrong?
fertig=tkinter.Tk()
fertig.title("Window")
text=tkinter.Label(fertig,text="Success")
text.pack()
w = tkinter.PhotoImage(file="/Users/Hannes/Desktop/Spambot/successful.gif ")
w = tkinter.label(fertig,image=w)
w.pack()
knapp=tkinter.Button(fertig,text="Ok",command=lambda:close())
knapp.pack()
knapp.mainloop()
The following works for me on my Windows system. I had to fix and add a few (unrelated) things to get the code in your question to work, but after doing so I found the real reason the image doesn't display.
So, the error that relates most directly to the that problem is because you're overwriting the variable w: After you assign a tkinter.PhotoImage() value to it, you immediately assign a another value (the tkinter.Label) to using its current value (image=w). The second assignment causes the tkinter.PhotoImage() object that was in it to be lost. Since there are no more references to to, it will be garbage-collected at some point.
To fix that, I simply assign the PhotoImage object to a separate variable img.
Note, too, that (apparently) having the trailing space character in the filename isn't a problem (at least not on Windows).
Here's some "official" documentation specifically about the PhotoImage class that discusses the need for keeping a reference around to the original—see the NOTE: at the end—when using it with other tkinter widgets (like a Label).
import tkinter
def close(): # just a placeholder implementation.
print('close() called')
fertig=tkinter.Tk()
fertig.title("Window")
text=tkinter.Label(fertig, text="Success")
text.pack()
#w = tkinter.PhotoImage(file="/Users/Hannes/Desktop/Spambot/successful.gif ")
img = tkinter.PhotoImage(file=r"C:\vols\Files\PythonLib\Stack Overflow\successful.gif ")
w = tkinter.Label(fertig, image=img)
w.pack()
knapp=tkinter.Button(fertig, text="Ok", command=lambda: close())
knapp.pack()
knapp.mainloop()
Here's what it looks like (using an image of my own).
Related
I know how to change a label's color with a command attached to a button, but I want to do it programmatically, based on a variable's value.
If an error message is sent to the build_window function, I want to display the error message on a label with a red background, and if a non-error message is sent, no message is to be displayed and no color changes are expected.
In my code, I call the function to build a tkinter window two times.
The first time, I pass it a non-error message, the second time, an error message.
My code works for displaying the error message when expected, the problem is only with changing the background color of the error message label.
If I un-comment the l1.config(bg="red") command shown, I get this error when passing an error message to build_window():
UnboundLocalError: local variable 'l1' referenced before assignment
on the l1.config(bg="red") command.
If I move the entire if structure to just before mainloop(), I get this error even when passing the non-error message:
UnboundLocalError: local variable 'error_message' referenced before assignment
on the l1=Label(root,text = error_message) command.
If I add global l1 and global error_message to build_window(), the error I get is this:
tkinter.TclError: invalid command name ".!label"
I also tried just initially defining the label with bg="red", hoping that when I send a zero-length string, it would still be gray, but it displays a bit of red in the middle of the l1 label.
I've been writing simple python for a while, but I'm new to GUI apps and tkinter just confuses me every time I try something.
I've searched for a solution but could not find anything addressing changing a window without using a command attached to a button.
Any advice or clarification would be greatly appreciated!
from tkinter import Tk, IntVar, Label, mainloop, Button
def build_window(incoming_error_message) :
if incoming_error_message == "initial value" :
error_message = ""
else :
#l1.config(bg="red")
error_message = incoming_error_message
def quitHandler():
root.destroy()
root = Tk()
l1=Label(root,text = error_message)
l1.grid(row=0,column=0)
quitButton = Button(root, text="To end, click here",command=quitHandler)
quitButton.grid(row=1,column=0)
mainloop()
def call_build_window() :
build_window("initial value")
build_window("Error!")
call_build_window()
One option is to place the label creation within the condition and reorder the surrounding code a little bit. I also replaced grid by pack and skipped keeping names for variables which are actually constants, all that changes were made to keep the code small:
from tkinter import Tk, Label, mainloop, Button
def build_window(error_message):
root = Tk()
if error_message == "initial value":
Label(root, text="").pack()
else:
Label(root, text=error_message, bg="red").pack()
def quitHandler():
root.destroy()
Button(root, text="To end, click here", command=quitHandler).pack()
mainloop()
def call_build_window():
build_window("initial value")
build_window("Error!")
call_build_window()
This of course is a small case study and shouldn't be used to build on it.
I think it should be reworked so that there is a maybe function that takes the indicator if the message is as a second argument with the text always being displayed. All that would be much easier in a more object-oriented approach. (Also remember that Tk() is normally called only once and secondary top-level windows are created via Toplevel(), see Python - Tkinter - invisible text in ttk.Entry in sub window or tkinter: Open a new window with a button prompt. )
By using tkinter.ttk it's also possible to change the widget's style at runtime, see the answer to Changing ttk widget text color for an example.
I know this question has been asked quite often, but I still can't figure out what's the problem:
I'm trying to make a simple Tkinter window with 4 Buttons. Each one should have a background Image. When I try to set image=path+'image.png' I get this: _tkinter.TclError: image "C:/Users/.../image.png" doesn't exist. The strange thing is that when I copy the path from the message and paste it into the Explorer adress line it opens the image i want to have as background image.
Here's the necessary code:
import tkinter
global path
path = 'C:/Users/Michael Hofmann/.../kahoot'
root = tkinter.Tk()
Button_red = tkinter.Button(root, image=path+'/images/red_small.png', command= pressed('red'))
Thanks in advance!
The error is telling you an image object doesn't exist by that name, not that a file doesn't exist by that name. The image option requires an object of type tkinter.PhotoImage. You can't just give it a path to an image.
image = tkinter.PhotoImage(file=path+'/images/red_small.png')
Button_red = tkitner.Button(..., image=image)
I have a fairly lengthy GUI image viewing program, the "globals" started to get out of hand and I have eliminated them all but one. The simplified code below shows the global variable art. with it in place the image is displayed, without it - a grey screen. I would appreciate any help in understanding what is going on
from tkinter import *
from PIL import ImageTk,Image
root = Tk()
def image():
global art
path="c:/Google Drive/Art Images/0030#Van Tromp, going about to please his Masters.jpg"
image=Image.open(path)
art = ImageTk.PhotoImage(image)
label.grid()
label.configure(image=art)
label=Label(root,bg="grey")
image()
root.mainloop()
Your issue is that when creating a Photoimage, you need to keep a reference to that image, meaning you need to assign that image a variable name that can be accessed elsewhere. In your case, the variable art, without using a global, stays in the function. This means that when the function finished, art is destroyed. An easy fix is to return the variable art, making the output of the function art, and thus bringing the variable into the main code. This is what effbot has to say about that:
When you add a PhotoImage or other Image object to a Tkinter widget, you must keep your own reference to the image object. If you don’t, the image won’t always show up.
The problem is that the Tkinter/Tk interface doesn’t handle references to Image
objects properly; the Tk widget will hold a reference to the internal object, but Tkinter does not. When Python’s garbage collector discards the Tkinter object, Tkinter tells Tk to release the image. But since the image is in use by a widget, Tk doesn’t destroy it. Not completely. It just blanks the image, making it completely transparent
To fix this, you could use a global variable (which can be accessed elsewhere in the main code, thus becoming a 'reference'), or you could do something like this:
from tkinter import *
from PIL import ImageTk,Image
root = Tk()
def image():
label.grid()
path="c:/Google Drive/Art Images/0030#Van Tromp, going about to please his Masters.jpg"
image=Image.open(path)
art = ImageTk.PhotoImage(image)
label.configure(image=art)
return art
label=Label(root,bg="grey")
image()
root.mainloop()
In that code, your image is returned by the function and assigned a variable in the main code, making is a 'reference' without globals.
You can find more info here
Your function, image(), is being used to output your image, and to do that, you're assigning it to the variable 'art'. An image object is created, but when your function ends, since you aren't returning anything, that object ceases to exist:
y = 5
def getx():
x = 3
getx()
a = y + x
This code won't work, because x is local to the function getx(). Since I'm not doing anything with it, when the function ends, so does the variable. What I can do, though, is pass data out of the function, like this:
y = 5
def getx():
x = 3
return x
x = getx()
a = y + x
In your code, tkinter needs for the image object to exist when it runs, but while you created it within your function, you let the function end without doing anything with it. Naming art a global variable effectively allows your function to return your object to a variable outside of the function. Another way to do it, though would be:
root = Tk()
def image():
path="c:/Google Drive/Art Images/0030#Van Tromp, going about Masters.jpg"
image=Image.open(path)
art = ImageTk.PhotoImage(image)
label.grid()
label.configure(image=art)
return art
label=Label(root,bg="grey")
art = image()
root.mainloop()
all. I'm working on a simple Notepad-like program that saves files and closes the program when the escape key is pressed. I mention this because it is in this method that the program runs into problems. textpad is a ScrolledText object.
This line:
`contents = self.textPad.get(self, 1.0, END)`
results in the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/usr/lib/python2.7/lib-tk/Tkinter.py", line 1535, in __call__
return self.func(*args)
File "todopad.py", line 24, in save_and_quit
contents = self.textPad.get(self, 1.0, END)
AttributeError: Event instance has no attribute 'textPad'
I know this is the problem, because the program executes and terminates without issue when this line is commented out. Although I don't understand the error at all.
This has been a very long-winded way of asking: How can I retrieve the contents of a ScrolledText text pad and save it to a variable or directly write it to a file? And also an explanation about the error message?
Thank you in advance.
EDIT: As requested, here is the code for the entire thing.
import sys
import Tkinter
from Tkinter import *
from ScrolledText import *
root = Tkinter.Tk(className = "TodoPad");
textPad = ScrolledText(root, width = 80, height = 20)
def start_and_open():
textFile = open('/home/colin/documents/prog/py/todopad/todo', 'r')
contents = textFile.read()
textPad.insert('1.0', contents)
textFile.close()
def save_and_quit(self):
textFile = open('/home/colin/documents/prog/py/todopad/todo', 'w')
#contents = self.textPad.get(self, 1.0, END) # The line in question
#textFile.write(contents)
textFile.close()
root.destroy()
textPad.pack()
root.bind('<Escape>', save_and_quit)
root.after(1, start_and_open)
root.mainloop()
Since I have posted the whole thing I may as well explain the rationale behind everything. It's supposed to be a fast little thing that opens a to-do list and displays what's already on the list in the text box. I make whatever edits I like, then it saves before closing when I hit escape, problem being is that it doesn't like closing because of the line that I mentioned previously in my post.
First of all, kudos on identifying the problem.
Placing the Widget
To answer what is going wrong: you need to actually place the widget into the window frame. You have a choice between .grid() and .pack(). The first allows you to pick exactly where you want it to go, the second puts in a (technically) default location.
Right now, the instance of your widget is not preset, so your program has no idea where to pull the value from. You have to set a location. i would recommend using .grid(), but for the example .pack() will work as well.
textPad = ScrolledText(root, width = 80, height = 20)
textPad.pack()
Try this, and see if it works. This should fix it, but I could be wrong.
Do NOT just do
textPad = ScrolledText(root, width = 80, height = 20).pack()
The pack() function returns a NULL and will nullify your widget.
Your Issue With Self
Finally, why are you using self at all? You are not using any classes--you need to globalize the variable. The error that is thrown is a result of your program not knowing what class you are pulling the self instance from. Remove the self variables from the program, and put this into the function:
global textPad
This will make it global and all functions will be able to use it.
This should solve all the problems you have right now. However, give it a try and report what happens.
Here are some resources on global variables, getting input from widgets, and saving to files;
http://www.python-course.eu/python3_global_vs_local_variables.php
http://effbot.org/tkinterbook/text.htm
http://www.afterhoursprogramming.com/tutorial/Python/Writing-to-Files/
Happy coding, and best of luck!!
After seeing this, PhotoImage not showing up the image associated with it I wondered why omitting the type of option does not throws an error instead of just not showing up the image?
This code does not show the image without throwing any error
import tkinter as tk
root = tk.Tk()
image1 = tk.PhotoImage("ban.gif")
tk.Label(root,image=image1).pack()
tk.Label(root, text="some string here").pack()
root.mainloop()
But this one works fine
import tkinter as tk
root = tk.Tk()
image1 = tk.PhotoImage(file="ban.gif")
tk.Label(root,image=image1).pack()
tk.Label(root, text="some string here").pack()
root.mainloop()
On effbot it doesn't say anything about it so I checked tcl man page for creating photos but still can not find why it behaves like this.
Also, if those two are duplicate ones, let me know so I will delete/close vote this one.
When you specify a function with named arguments in python, those named arguments appear in a specific order. If you do not supply a name when defining these arguments, they are applied in the order that the arguments appear in the function definition.
In the case of PhotoImage, the first keyword argument is for the name of the image, not a path to a file. So, PhotoImage("ban.gif") is the same as doing PhotoImage(name="ban.gif"). It doesn't throw an error because "ban.gif" is a valid name, and there are use cases where you want to create an image without referencing a file.