【问题标题】:Python Tkinter .jpeg Image not displaying -- TclErrorPython Tkinter .jpeg 图像未显示——TclError
【发布时间】:2015-10-23 21:04:40
【问题描述】:

我正在尝试将.jpeg 图像添加到我的 GUI 中,同时它还有其他几个小部件。

使用我的代码,当我使用以下命令时,我可以在单独的Tkinter 窗口中显示图像:

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

但是,每当我尝试将图像添加到原始 Tkinter 窗口时,都会在代码下方看到错误。我尝试将其添加到原始 Tkinter 窗口的方式是:

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

复制错误

奇怪的是,当我尝试在较短的代码版本中复制错误时(例如直接在下面),它可以工作。然而!要在缩短的代码中复制错误,您需要先创建一个不同的错误。示例:将text = "Try" 替换为text = "%s" %yikes(因为没有变量yikes 它会给你一个错误)。将代码更改回之前的确切方式后,它会产生我在下面描述的错误 (TclError: image "pyimage__" doesn't exit)。在最底部,我已经包括了整个班级,因为我很难始终如一地复制这个问题。我正在使用 Python 2.7 和 Canopy 1.5.5。

短代码:

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()

当我使用注释掉的方法时,我在程序中收到错误:

    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 

几乎完整的代码:

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()

【问题讨论】:

  • 我怀疑您发布的代码距离成为 mcve stackoverflow.com/help/mcve 还有很长的路要走。目前尚不清楚为什么将图像放在画布上而不是直接放在框架上。如果你做后者,还是同样的问题?我会尝试直接使用 python 而不是您使用的任何 IDE 运行代码。还要考虑错误消息。 pyimage7 大概是 self.img。在调用之前添加print(self.img),看看它到底是什么。
  • 我很抱歉,我之前没有看到那个链接。我已经编辑了我的代码以尝试使其更加 mcve(尽管我在底部包含了整个代码的大部分以防需要更多上下文)。您如何将图像放在框架上?正如我所说,我对 Python 很陌生。
  • 查看effbot.org/tkinterbook/photoimage.htm了解其他使用图像的方法。我再说一遍,在没有 Canopy 的情况下运行您的代码,看看 Canopy 是否是问题所在。如果需要,请尝试使用 IDLE 编辑器进行编辑和运行,因为 IDLE 旨在能够运行 tkinter 程序,并且目前没有关于 IDLE 在这样做时遇到问题的报告。
  • 我目前正在使用链接为 .jpg 图像建议的格式。我将代码直接放在 IDLE 中,我得到了同样的错误。

标签: python image class tkinter canopy


【解决方案1】:

您需要对框架进行网格化。当我添加

frame.grid()

在您的 __init__ 方法的底部,它可以正常工作。不过,当我运行您发布的代码时,我没有收到错误消息。它只是不显示标签。我想知道这是否是一些依赖于平台的行为。我在优胜美地 10.10.5 上使用 python 2.7。

编辑:我已经尝试了您的扩展示例,并且正如预期的那样,我没有看到您的行为。我可以来回更改代码。当它不正确时,我得到一个错误;当它正确时,它运行良好。

您描述的行为一定与 Canopy 有关。 python解释器的工作方式,每次运行时都会将脚本编译成字节码;它对脚本过去所说的一无所知。

您可以尝试从命令行运行可疑脚本吗?此外,也许您应该在您的问题中添加canopy 标签。

我不使用 Canopy,所以我认为我不能帮助您,但我将答案留在这里作为希望可以帮助的人的背景。

祝你好运。

【讨论】:

  • 我实际上在原始代码中对框架进行了网格化。当我运行缩短的示例时,它也对我有用。我无法弄清楚为什么它在我的实际较长代码中不起作用(发布在底部)。
  • 您是否使用了我的错误示​​例?另外,我已经将我的实际代码直接尝试到 Python IDLE 中,但我得到了同样的错误。这让我觉得这不是 Canopy 问题。
  • 是的,我使用了您的确切示例。如果它也在 IDLE 中发生,那么这不是 Canopy 问题,但我无法在这里重现。
【解决方案2】:

我发现了问题!!

我在代码的最开头使用了askopenfilename(),它打开了一个额外的Tkinter 窗口。结果,打开了两个Tkinter 窗口并混淆了程序。

通过将所有内容发送到创建的第一个 Tk 窗口(并删除第二个),它解决了问题。

【讨论】:

    猜你喜欢
    • 2020-11-04
    • 2022-01-04
    • 2019-04-30
    • 2021-05-11
    • 1970-01-01
    • 1970-01-01
    • 2012-02-06
    • 2017-01-19
    • 1970-01-01
    相关资源
    最近更新 更多