Search code examples
pythonimageclasstkintercanopy

Python Tkinter .jpeg Image not displaying -- TclError


I'm attempting to add a .jpeg image to my GUI while it has several other widgets.

With my code, I can display the image in a separate Tkinter window when I use the following command:

#self.label = Label(image = self.img)

However, whenever I try to add the image to the original Tkinter window, I get the error seen below my code. The way I tried to add it to the original Tkinter window is:

#self.label = Label(frame, image = self.img)

Replicating the error

Oddly enough, when I try to replicate the error in a shorter version of the code (such as directly below), it works. HOWEVER! To replicate the error in the shortened code, you need to create a different error first. Example: Replace text = "Try" with text = "%s" %yikes (because there is no variable yikes it will give you an error). After you change the code back to the EXACT way it was before, it produces the error I've descried below (TclError: image "pyimage__" doesn't exit). At the very bottom, I've included the entire class since I'm having difficulty consistently replicating the issue. I'm using Python 2.7 and Canopy 1.5.5.

Shortened code:

import matplotlib.pyplot as plt
from Tkinter import *
from PIL import ImageTk, Image
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
from tkFileDialog import askopenfilename, askdirectory

class App:

    def __init__(self, master):
        frame = Frame(master)

        self.button_left = Button(frame,text="< Previous Event")
        self.button_left.grid(row=1,column=0)
        self.button_right = Button(frame,text="Next Event >")
        self.button_right.grid(row=1,column=3)

       #Creating text for the UI indicating the number of leakage events
        w = Label(frame, text="Trying to Recreate error")
        w.grid(row=1,column=2)

        self.m = Canvas(frame,width=50,height=25)
        self.text_id = self.m.create_text(25,12.5, text="Try")
        self.m.grid(row=1,column=1)


        self.path = "C:\Carbonite\EL_36604.02_231694\EL_36604.02_231694_2015-06-15 10.39.57.jpeg"
        self.image = Image.open(self.path)
        self.img = ImageTk.PhotoImage(self.image)
        #self.label = Label(image = self.img)
        self.label = Label(frame,image = self.img)
        self.label.image = self.img
        self.label.grid(row = 3, column = 0)
        frame.grid(row=0,column=0)

root = Tk()
app = App(root)
root.mainloop()

Error I receive in my program when I use the commented out method:

    TclError                                  Traceback (most recent call last)
C:\Carbonite\Main_interface_file.py in <module>()
    136 
    137 root = Tk()
--> 138 app = App(root)
    139 root.mainloop()
    140 

C:\Carbonite\Main_interface_file.py in __init__(self, master)
     72         self.img = ImageTk.PhotoImage(self.image)
     73         #self.label = Label(image = self.img)
---> 74         self.label = Label(frame,image = self.img)
     75         self.label.image = self.img
     76         self.label.grid(row=3, column = 0)

C:\Users\U10596\AppData\Local\Enthought\Canopy\App\appdata\canopy-1.5.5.3123.win-x86_64\lib\lib-tk\Tkinter.pyc in __init__(self, master, cnf, **kw)
   2585 
   2586         """
-> 2587         Widget.__init__(self, master, 'label', cnf, kw)
   2588 
   2589 class Listbox(Widget, XView, YView):

C:\Users\U10596\AppData\Local\Enthought\Canopy\App\appdata\canopy-1.5.5.3123.win-x86_64\lib\lib-tk\Tkinter.pyc in __init__(self, master, widgetName, cnf, kw, extra)
   2084                 del cnf[k]
   2085         self.tk.call(
-> 2086             (widgetName, self._w) + extra + self._options(cnf))
   2087         for k, v in classes:
   2088             k.configure(self, v)

TclError: image "pyimage8" doesn't exist 

Almost entire Code:

import matplotlib.pyplot as plt
from Tkinter import *
from PIL import ImageTk, Image
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg
from matplotlib.figure import Figure
import numpy as np
from images_to_list import images_to_list
from tkFileDialog import askopenfilename, askdirectory
#Creating a class that creates the UI
class App:

    def __init__(self, master):

        self.event_num = 1
        # Create a container
        frame = Frame(master)

        # Create 2 buttons (changes between leakage events
        self.button_left = Button(frame,text="< Previous Event",
                                        command=self.decrease)
        self.button_left.grid(row=1,column=0)
        self.button_right = Button(frame,text="Next Event >",
                                        command=self.increase)
        self.button_right.grid(row=1,column=3)

       #Creating text for the UI indicating the number of leakage events
        w = Label(frame, text="/  %s  " % len(tft))
        w.grid(row=1,column=2)

        #Display the number of the current event in the series
        self.m = Canvas(frame,width=50,height=25)
        self.text_id = self.m.create_text(25,12.5, text="%s" % (self.event_num+1))
        self.m.grid(row=1,column=1)

        #Creating the plot of voltage data
        self.fig = Figure()
        self.ax = self.fig.add_subplot(111)
        self.fig.autofmt_xdate()
        import matplotlib.dates as mdates
        self.ax.fmt_xdata = mdates.DateFormatter('%Y-%m-%d')
        self.line, = self.ax.plot(tft[self.event_num],tf1[self.event_num],'.')
        self.line2, = self.ax.plot(tft[self.event_num],tf2[self.event_num],'.')
        self.ax.set_ylim([0,3.5])


        self.path = "C:\Carbonite\EL_36604.02_231694\EL_36604.02_231694_2015-06-15 10.39.57.jpeg"
        self.image = Image.open(self.path)
        self.img = ImageTk.PhotoImage(self.image)
        #self.label = Label(image = self.img)
        self.label = Label(frame,image = self.img)
        self.label.image = self.img
        self.label.grid(row=3, column = 0)


        self.canvas = FigureCanvasTkAgg(self.fig,master=master)
        self.canvas.show()
        self.canvas.get_tk_widget().grid(row=1,column=0)
        frame.grid(row=0,column=0)

        #Creating a textbox to jump to event number
        self.textbox = Entry(frame,width=5)
        button1 = Button(frame, text='Go', command=self.letsgo) #Linking "Go" button with letsgo function to jump to event number
        self.textbox.grid(row=2,column=1)
        button1.grid(row=2,column=2)

    #function letsgo allows the user to jump to any event in the series    
    def letsgo(self):
        txt = self.textbox.get()
        try:
            self.event_num = int(txt)
        except ValueError:
            print "Opps! The number you enter needs to be an integer!"
        self.line.set_xdata(tft[self.event_num])
        self.line.set_ydata(tf1[self.event_num])
        self.line2.set_xdata(tft[self.event_num])
        self.line2.set_ydata(tf2[self.event_num])
        self.ax.set_xlim([min(tft[self.event_num]),max(tft[self.event_num])])
        self.canvas.draw()
        self.m.itemconfig(self.text_id, text="%s" % (self.event_num+1))

     #function decrease allows the user to use the decrease button                
    def decrease(self):
        if self.event_num == 0: #if statement accounts for if the user tries to see the event previous to the first one
            self.event_num = len(tft)-1
        else:
            self.event_num -= 1
        self.line.set_xdata(tft[self.event_num])
        self.line.set_ydata(tf1[self.event_num])
        self.line2.set_xdata(tft[self.event_num])
        self.line2.set_ydata(tf2[self.event_num])
        self.ax.set_xlim([min(tft[self.event_num]),max(tft[self.event_num])])
        self.canvas.draw()
        self.m.itemconfig(self.text_id, text="%s" % (self.event_num+1))

    #function increase allows the user to use the increase button            
    def increase(self):
        if self.event_num == len(tft)-1: #if statement accounts for if the user tries to see the event after the last one.
            self.event_num = 0
        else:
            self.event_num += 1        
        self.line.set_xdata(tft[self.event_num])
        self.line.set_ydata(tf1[self.event_num])
        self.line2.set_xdata(tft[self.event_num])
        self.line2.set_ydata(tf2[self.event_num])
        self.ax.set_xlim([min(tft[self.event_num]),max(tft[self.event_num])])
        self.canvas.draw()
        self.m.itemconfig(self.text_id, text="%s" % (self.event_num+1))





root = Tk()
app = App(root)
root.mainloop()

Solution

  • I found the issue!!

    I used askopenfilename() in the very beginning of my code, which opened an extra Tkinter window. As a result, there were two Tkinter windows open and confused the program.

    By sending everything to the first Tk window that was created (and removing the second), it resolved the issue.