Button Picture Attribute issues with Tkinter - python

I'm having weird issues with some iterated buttons that are made inside of a function. I have my button list as a global variable and photos are saved within my main python folder.
When I use the Button image= attribute, the buttons aren't clickable and are kind of greyed out with no picture. When I use the Button text= attribute, the buttons are clickable and the text pops up, but the width and height attributes don't run. I haven't been able to find similar issues/answers here.
from tkinter import *
from tkinter import filedialog as fd
from tkinter.messagebox import showinfo
from PIL import Image, ImageTk
def OnSomeClick():
---Some Code---
if Orientation == 1:
for i in range(len(Ordered_xCoord)):
InitButtonPhoto = '{}.png'.format(i)
ButtonPhoto = PhotoImage(file=InitButtonPhoto)
ImageButtonList.append(Button(action_window, command=Command, bd=3, width=110,
height=85, image=ButtonPhoto))
ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
#this top if statement is what runs with my test; the bottom is my original
else:
for i in range(len(Ordered_xCoord)):
ImageButtonList.append(Button(action_window,
image=PhotoImage(file='{}.png'.format(i)),
command=Command, bd=3, width=85, height=110))
ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
When loading the photo through PhotoImage(Image.open(file)), there is a traceback error. I'm not too sure why my photos are out of scope/garbaged or why the command working is dependent on the photo saving.
Traceback Error with Image.open:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 1892, in __call__
return self.func(*args)
File "/Users/PycharmProjects/CoordinateMath/TkinterWindow.py", line 163, in Submit
ButtonPhoto = PhotoImage(file=InitButtonPhoto)
File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 4064, in __init__
Image.__init__(self, 'photo', name, cnf, master, **kw)
File "/Users/.conda/envs/CoordinateMath/lib/python3.8/tkinter/__init__.py", line 4009, in __init__
self.tk.call(('image', 'create', imgtype, name,) + options)
_tkinter.TclError: couldn't open "<PIL.PngImagePlugin.PngImageFile image mode=RGB size=990x765 at 0x11034C310>": no such file or directory

Thank you, Matiiss and BryanOakley! The fix was a combo of the latest comment and putting my changing the formatting of my image list.
def onClick():
global Image_List, Ordered_xCoord, Ordered_yCoord, ImagedButtonList
--some code---
for i in range(len(Ordered_xCoord)):
y = myimage.save('{}.png'.format(i))
z = ImageTk.PhotoImage(Image.open('{}.png'.format(i)))
Image_List.append(z)
---more code----
if PaperOrientation == 1:
for i in range(len(Ordered_xCoord)):
InitButtonPhoto = Image_List[i]
ButtonPhoto = InitButtonPhoto
ImageButtonList.append(Button(action_window, command=Command, bd=3, width=110,
height=85, image=ButtonPhoto))
ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
else:
for i in range(len(Ordered_xCoord)):
InitButtonPhoto = Image_List[i]
ButtonPhoto = InitButtonPhoto
ImageButtonList.append(Button(action_window, command=Command, bd=3, width=85,
height=110, image=ButtonPhoto))
ImageButtonList[i].grid(row=Ordered_yCoord[i], column=Ordered_xCoord[i])
Kind of sloppy on my part, but it works.

Related

"_tkinter.TclError: image "pyimage2" doesn't exist"

I'm trying to fix this and I don't know how... When I click on the first button the second doesn't appear. It raises this exception:
_tkinter.TclError: image "pyimage2" doesn't exist
I tried everything but I don't know what to do anymore.
Error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 1892, in __call__
return self.func(*args)
File "test\main.py", line 26, in <lambda>
boutonAlphabetMaj.bind("<Leave>", lambda e: boutonAlphabetMaj.config(fg='#3f3f3f', bg='#383838'))
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 1646, in configure
return self._configure('configure', cnf, kw)
File "C:\Program Files\Python39\lib\tkinter\__init__.py", line 1636, in _configure
self.tk.call(_flatten((self._w, cmd)) + self._options(cnf))
_tkinter.TclError: image "pyimage2" doesn't exist
Code:
import tkinter as tk
from tkinter import font
from PIL import ImageTk, Image
import time
import os
# Root
root = tk.Tk()
root.minsize(1920, 1080)
root.maxsize(1920, 1080)
# Frame + Canvas
frame = tk.LabelFrame(root, borderwidth=0)
canvas = tk.Canvas(frame, height=1080, width=1920, borderwidth=0, bg="#383838")
frame.grid()
canvas.grid()
# Fonctions
def alphabet() :
canvas.delete("boutonAlphabet")
# Bouton Alphabet Majuscule
pathAlphabetMaj = os.path.join("test/alphabetMaj.png")
pictureAlphabetMaj = Image.open(pathAlphabetMaj)
picAlphabetMaj = ImageTk.PhotoImage(pictureAlphabetMaj)
boutonAlphabetMaj = tk.Button(canvas, image=picAlphabetMaj, borderwidth=0, bg="#383838", activebackground="#4a4a4a", cursor="hand2")
picAlphabetMaj.pictureAlphabetMaj = pictureAlphabetMaj
boutonAlphabetMaj.bind("<Enter>", lambda e: boutonAlphabetMaj.config(fg='#383838', bg='#3f3f3f'))
boutonAlphabetMaj.bind("<Leave>", lambda e: boutonAlphabetMaj.config(fg='#3f3f3f', bg='#383838'))
canvas.create_window(200, 500, window=boutonAlphabetMaj, tags=("boutonAlphabetMaj"))
# Titre
canvas.create_text(960, 50, text="APPRENDRE LE FRANÇAIS", font=("",50), fill="white")
# Bouton Alphabet
pathAlphabet = os.path.join("test/alphabet.png")
pictureAlphabet = Image.open(pathAlphabet)
picAlphabet = ImageTk.PhotoImage(pictureAlphabet)
boutonAlphabet = tk.Button(canvas, image=picAlphabet, borderwidth=0, bg="#383838", activebackground="#4a4a4a", command=lambda: alphabet(), cursor="hand2")
picAlphabet.pictureAlphabet = pictureAlphabet
boutonAlphabet.bind("<Enter>", lambda e: boutonAlphabet.config(fg='#383838', bg='#3f3f3f'))
boutonAlphabet.bind("<Leave>", lambda e: boutonAlphabet.config(fg='#3f3f3f', bg='#383838'))
canvas.create_window(200, 250, window=boutonAlphabet, tags=("boutonAlphabet"))
# loop
root.mainloop()
You have common problem with bug in ImagePhoto which removes image when it is assigned to local variable in function. You have to assign it to global variable or to class.
It seems you try to resolve this problem but you use wrong variables.
You assign Image.open() to PhotoImage .
picAlphabetMaj.pictureAlphabetMaj = pictureAlphabetMaj
but you should assign PhotoImage to button boutonAlphabetMaj
boutonAlphabetMaj.pictureAlphabetMaj = picAlphabetMaj

"_tkinter.TclError: image "pyimage4" doesn't exist" [duplicate]

This question already has answers here:
_tkinter.TclError: image "..." doesn't exist
(3 answers)
Closed 4 years ago.
Here is part of my code called within a function:
#Labels and Window layout
lsfpy = Tk()
lsfpy.title("Helicopters Sydney")
lsfpy.resizable(False, False)
Label(lsfpy, text="Locations in Sydney").grid(row=0)
Label(lsfpy, text="To").grid(column = 1, row=1, sticky=N)
Label(lsfpy, text="From").grid(column = 1, row=2, sticky = W)
Label(lsfpy, text="").grid(column = 1, row=3)
Label(lsfpy, text="Date").grid(column = 1, row=4, sticky=SW)
Label(lsfpy, text="Time").grid(column = 1, row=5, sticky=SW)
#Map
photo = PhotoImage(file = 'GUI Files/Map/Sydmap.gif')
photo = photo.subsample(2)
lbl = Label(lsfpy,image = photo)
lbl.grid(column=0, row=3)
When I run it, I get this error:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
return self.func(*args)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 22, in calculateandnext
saveandgotomapf(tp,am1,am2,am3,am4,am5)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 55, in saveandgotomapf
locationfreight(fdpy)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Locationfreight.py", line 192, in locationfreight
lbl = Label(lsfpy,image = photo)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2763, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2296, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage4" doesn't exist
When I comment out
photo = photo.subsample(2)
The error slightly changes to:
Exception in Tkinter callback
Traceback (most recent call last):
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 1702, in __call__
return self.func(*args)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 22, in calculateandnext
saveandgotomapf(tp,am1,am2,am3,am4,am5)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Freight.py", line 55, in saveandgotomapf
locationfreight(fdpy)
File "/Users/62633/Documents/2018/SDD/Webdrone Sydney/Locationfreight.py", line 192, in locationfreight
lbl = Label(lsfpy,image = photo)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2763, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/tkinter/__init__.py", line 2296, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage3" doesn't exist
If I copy the code snippet into a new file, there are no problems.
What is causing these errors?
In your recent edit, you mentioned the code was in a function, that made all the difference.
The PhotoImage is not kept by tkinter, so you must keep a reference to it before Python's garbage collector gobbles up the image after the function returns. When it does, tkinter couldn't find your image anymore, thus your error saying that the image doesn't exist.
As recommended if effbot, you can do:
photo = PhotoImage(file = 'GUI Files/Map/Sydmap.gif')
photo = photo.subsample(2)
lbl = Label(lsfpy,image = photo)
lbl.image = photo
lbl.grid(column=0, row=3)
You must keep a reference to the image object in your Python program,
either by storing it in a global variable, or by attaching it to
another object.
Note: When a PhotoImage object is garbage-collected by
Python (e.g. when you return from a function which stored an image in
a local variable), the image is cleared even if it’s being displayed
by a Tkinter widget. To avoid this, the program must keep an extra
reference to the image object. A simple way to do this is to assign
the image to a widget attribute, like this:
label = Label(image=photo)
label.image = photo # keep a reference! label.pack()

Putting gif image in tkinter window

I'm trying to insert a gif image in a new tkinter window when a button is clicked but I keep getting this error
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Users\Afro\AppData\Local\Programs\Python\Python35\lib\idlelib\run.py", line 119, in main
seq, request = rpc.request_queue.get(block=True, timeout=0.05)
File "C:\Users\Afro\AppData\Local\Programs\Python\Python35\lib\queue.py", line 172, in get
raise Empty
queue.Empty
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "C:\Users\Afro\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 1549, in __call__
return self.func(*args)
File "C:/Users/Afro/Desktop/mff.py", line 8, in sex
canvas = tkinter.Label(wind,image = photo)
File "C:\Users\Afro\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2605, in __init__
Widget.__init__(self, master, 'label', cnf, kw)
File "C:\Users\Afro\AppData\Local\Programs\Python\Python35\lib\tkinter\__init__.py", line 2138, in __init__
(widgetName, self._w) + extra + self._options(cnf))
_tkinter.TclError: image "pyimage1" doesn't exist
Here's the code. The image and the location actually exists.
import tkinter
def six():
wind = tkinter.Tk()
photo = tkinter.PhotoImage(file = 'American-Crime-Story-1.gif')
self = photo
canvas = tkinter.Label(wind,image = photo)
canvas.grid(row = 0, column = 0)
def base():
ssw = tkinter.Tk()
la = tkinter.Button(ssw,text = 'yes',command=six)
la.grid()
base()
What am I doing wrong?
You are trying to create two instances of Tk window. You can't do that. If you want second window or pop-up window you should use Toplevel() widget.
Also, self doesn't mean anything in this context. Using the widget's image property would be better to keep a reference.
import tkinter
ssw = tkinter.Tk()
def six():
toplvl = tkinter.Toplevel() #created Toplevel widger
photo = tkinter.PhotoImage(file = 'American-Crime-Story-1.gif')
lbl = tkinter.Label(toplvl ,image = photo)
lbl.image = photo #keeping a reference in this line
lbl.grid(row=0, column=0)
def base():
la = tkinter.Button(ssw,text = 'yes',command=six)
la.grid(row=0, column=0) #specifying row and column values is much better
base()
ssw.mainloop()

_tkinter.TclError: can't pack when trying to add ttkcalendar into tkinter GUI

I'm trying to add a ttk calendar into my Tkinter GUI. The problem is that it raises _tkinter.TclError: can't pack .34164128 inside .34161248.34161448.34161608
import Tkinter
import tkSimpleDialog
import ttkcalendar
class CalendarDialog(tkSimpleDialog.Dialog):
"""Dialog box that displays a calendar and returns the selected date"""
def body(self, master):
self.calendar = ttkcalendar.Calendar(master)
self.calendar.pack()
def apply(self):
self.result = self.calendar.selection
# Demo code:
def main():
root = Tkinter.Tk()
root.wm_title("CalendarDialog Demo")
def onclick():
print 'click'
cd = CalendarDialog(root)
button = Tkinter.Button(root, text="Click me to see a calendar!", command=onclick)
button.pack()
root.update()
root.mainloop()
if __name__ == "__main__":
main()
TRACEBACK:
File "C:/Users/Milano/PycharmProjects/MC/plots/ds.py", line 32, in <module>
main()
File "C:/Users/Milano/PycharmProjects/MC/plots/ds.py", line 23, in main
cd = CalendarDialog(root)
File "C:\Python27\lib\lib-tk\tkSimpleDialog.py", line 64, in __init__
self.initial_focus = self.body(body)
File "C:/Users/Milano/PycharmProjects/MC/plots/ds.py", line 9, in body
self.calendar = ttkcalendar.Calendar(master)
File "C:\Users\Milano\PycharmProjects\MC\plots\ttkcalendar.py", line 52, in __init__
self.__place_widgets() # pack/grid used widgets
File "C:\Users\Milano\PycharmProjects\MC\plots\ttkcalendar.py", line 110, in __place_widgets
self._calendar.pack(in_=self, expand=1, fill='both', side='bottom')
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1940, in pack_configure
+ self._options(cnf, kw))
_tkinter.TclError: can't pack .34164128 inside .34161248.34161448.34161608
Do you know where is the problem?
The fault is that you don't have an __init__ method in the class CalendarDialog. So just rename the body method to __init__. Now you have initialized the instance every time one is made and a pack() method is defined.
I also encountered this problem putting a ttkCalendar into a Dialog box.
I suspect the author of this post "borrowed" the same code for building a calendar as I did:
https://www.google.com/url?sa=t&rct=j&q=&esrc=s&source=web&cd=2&ved=2ahUKEwiWgYWKsJ3nAhVKl3IEHYrhCU8QFjABegQICBAB&url=https%3A%2F%2Fsvn.python.org%2Fprojects%2Fpython%2Ftrunk%2FDemo%2Ftkinter%2Fttk%2Fttkcalendar.py&usg=AOvVaw0ifTox4EI7CtBFWlRYD_m9
There are two problems I found using this code to create a Calendar object and placing it into a Dialog box.
The first one causes the traceback as shown in the post. The fix is to modify the ttkcalendar.py file to pack the calendar when it is created, not after it is created using the pack() function.
Here is the diff:
102c102
< self._calendar = ttk.Treeview(show='', selectmode='none', height=7)
---
> self._calendar = ttk.Treeview(self, show='', selectmode='none', height=7)
109c109
< self._calendar.pack(in_=self, expand=1, fill='both', side='bottom')
---
> self._calendar.pack(expand=1, fill='both', side='bottom')
Once you make this change, the calendar will appear in the dialog box. However, your problems are not yet done. Another exception occurs when trying to set the minimum size of the calendar:
Exception in Tkinter callback
Traceback (most recent call last):
File "/home/richawil/Applications/anaconda3/envs/TLM/lib/python3.7/tkinter/__init__.py", line 1705, in __call__
return self.func(*args)
File "/home/richawil/Documents/Programming/Apps/TLM/TLM/ttkcalendar.py", line 134, in __minsize
width, height = self._calendar.master.geometry().split('x')
AttributeError: 'Calendar' object has no attribute 'geometry'
I have not been able to fix this issue other than to comment out the call to self.__minsize.
63c62,63
< self._calendar.bind('<Map>', self.__minsize)
---
> # Commented out because _calendar object does not support geometry() function
> #self._calendar.bind('<Map>', self.__minsize)

Error in trying to open dialog box from a widget button in python

I'm new to python. I'm trying to open a dialog box to get a value from within a widget that does a list of other staff allready.
But getting errors and can't figure out what to do.
Here's my code:
import Tkinter,Tkconstants,tkFileDialog
from Tkinter import *
import csv
import numpy
import math
import numpy.random as nrnd
import matplotlib.pyplot as plt
import shutil
import tkMessageBox
global filesavepath
class App:
def __init__(self,master):
self.mymaster=master
frame=Frame(master)
frame.pack()
self.importbutton=Button(frame,text='Import Data',command=self.importdata)
self.importbutton.pack()
self.executebutton=Button(frame,text='Execute',command=self.popup)
self.executebutton.pack()
self.distribution_rep=Button(frame,text='Repeat Purchase Score Distribution',command=self.distrepbutton)
self.distribution_rep.pack()
self.distribution_churn=Button(frame,text='Churn Probability Distribution',command=self.distchurnbutton)
self.distribution_churn.pack()
self.exitbutton=Button(frame,text='Exit',command=self.exitapp)
self.exitbutton.pack()
self.file_opt=options={}
options['defaultextension']=''
options['filetypes']=[('allfiles','.*'),('textfiles','.txt')]
options['initialdir']='C:\\'
options['initialfile']='myfile.txt'
options['parent']=root
options['title']='Thisisatitle'
def importdata(self):
filename=tkFileDialog.askopenfilename(**self.file_opt)
filesavepath="C:/input_full.csv"
shutil.copy2(filename,filesavepath)
if filename:
return open(filename,'r')
def popup(self):
top = self.top = Tkinter.Toplevel(self)
myLabel = Tkinter.Label(top, text='Enter your username below')
myLabel.pack()
self.myEntryBox = Tkinter.Entry(top)
self.myEntryBox.pack()
mySubmitButton = Tkinter.Button(top, text='Done', command=self.execbutton)
mySubmitButton.pack()
def execbutton(self):
if self.myEntryBox.get() != "":
self.timevalue = self.myEntryBox.get()
self.top.destroy()
execfile("Repeat Purchase Algo in python v6")
tkMessageBox.showinfo("Job Done", "Probability Computation completed")
def send(self):
global timevalue
timevalue=self.myEntryBox.get()
self.top.destroy()
def distrepbutton(self):
plt.hist(prob,bins=10,normed=TRUE)
plt.xlabel('Probability')
plt.title('Histogram of Repeat Purchase Probability')
plt.show()
def distchurnbutton(self):
plt.hist(churn_prob,bins=10,normed=TRUE)
plt.ylabel('Probability')
plt.title('Histogram of Churn Probability')
plt.show()
def exitapp(self):
self.mymaster.destroy()
root=Tk()
root.title('Repeat Puchase Widget')
app=App(root)
root.mainloop()
So as may be apparent to you, I'm importing dataset with an Import button, executing some analysis in another code through a button called Execute, and then showing some graphs.
What I wanted was to open a pop up kind of window on click of "Execute" button that will input a value. But I'm getting the following error:
Exception in Tkinter callback
Traceback (most recent call last):
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1410, in __call__
return self.func(*args)
File "C:/Python27/widget_repeat_purchase_v4", line 42, in popup
top = self.top = Tkinter.Toplevel(self)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 2017, in __init__
BaseWidget.__init__(self, master, 'toplevel', cnf, {}, extra)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1965, in __init__
BaseWidget._setup(self, master, cnf)
File "C:\Python27\lib\lib-tk\Tkinter.py", line 1943, in _setup
self.tk = master.tk
AttributeError: App instance has no attribute 'tk'
I've no idea what to do. Please help.
When you create the toplevel widget, you are passing self as the first argument. Tkinter requires that this be a parent widget. However, in your code self does not represent a widget.
In your specific case you want to pass in self.mymaster rather than self:
top = self.top = Tkinter.Toplevel(self.mymaster)
Use Tkinter.Toplevel() instead of Tkinter.Toplevel(self)

Categories

Resources