【问题标题】:Tkinter Image Updating Image + lambda ErrorTkinter 图像更新图像 + lambda 错误
【发布时间】:2018-05-29 05:15:44
【问题描述】:

最近我基本上是在自学 Tkinter。我已经在这个项目上工作了大约一个星期,我觉得它进展得相当顺利。今天,当我在处理它时,我得到了这段代码,它在成功运行时设置了 GUI。但是,当我尝试通过Combobox 更改图像时,它会失败并给我以下错误:

Exception in Tkinter callback
Traceback (most recent call last):
  File "C:\Users\user\AppData\Local\Programs\Python\Python36-32\lib\tkinter\__init__.py", line 1699, in __call__
    return self.func(*args)
TypeError: <lambda>() takes 0 positional arguments but 1 was given

经过快速搜索,我发现使用lambda x: 可以修复此错误。进行此更改后,GUI 将正常启动,但图像仍然不会更改,事实上,如果从第一个 Combobox 中选择了一个项目,第二个面板会出现故障并删除图像。完全删除“lambda”会导致面板根本无法启动。基本上,我想知道是什么导致了这些故障以及如何更新我的图像。

from tkinter import *
from tkinter.ttk import *
from PIL import Image, ImageTk
import os

class App(Frame):
    def __init__(self, parent):
        Frame.__init__(self, parent)
        self.parent = parent
        parent.title('Vainglory DMG Calculator | BETA')
        self.dyn_panel = []
        self.dyn_combobox = []
        self.dyn_image_path = ['', '']
        self.dyn_img = ['', '']
        self.cwd = os.getcwd()
        self.hero_list = ('Adagio', 'Alpha', 'Ardan', 'Baptiste', 'Baron', 'Blackfeather', \
                          'Catherine', 'Celeste', 'Churnwalker', 'Flicker', 'Fortress', \
                          'Glaive', 'Grace', 'Grumpjaw', 'Gwen', 'Idris', 'Joule', \
                          'Kestrel', 'Koshka', 'Krul', 'Lance', 'Lorelai', 'Lyra', 'Ozo', \
                          'Petal', 'Phinn', 'Reim', 'Reza', 'Ringo', 'Rona', 'Samuel', \
                          'SAW', 'Skaarf', 'Skye', 'Taka', 'Varya', 'Vox')
        for i in range(2):
            self.create_hero_combo_box(parent, i)
            self.set_image(i)            
            self.create_hero_panel(parent, self.dyn_img[i], i)

    def create_hero_panel(self, window, img, index):
        self.dyn_panel.append(Label(window, image=img))
        self.dyn_panel[index].grid(row=0, column=index*2)

    def create_hero_combo_box(self, window, index):
        self.dyn_combobox.append(Combobox(window, values=(*self.hero_list,)))
        self.dyn_combobox[index].grid(row=1, column=index*2)
        self.dyn_combobox[index].set(self.hero_list[0])

    def set_image(self, index):
        self.dyn_image_path[index] = (self.cwd + '/img/heroes/' + self.dyn_combobox[index].get().lower() + '.png')
        self.dyn_img[index] = ImageTk.PhotoImage(Image.open(self.dyn_image_path[index]))

    def update(self, index):
        self.dyn_panel[index].configure(image=self.set_image(index))

if __name__ == '__main__':
    root = Tk()
    app = App(root)
    for i in range(2):
        app.dyn_combobox[i].bind('<<ComboboxSelected>>', lambda x: app.update(i))
    root.mainloop()

【问题讨论】:

  • 最好使用lambda x=i : app.update(x),因为这样它将使用来自i 的正确值,而不是引用i,这将保持不同的值。
  • 这样做后我得到一个新错误:File "C:\Users\brigh\Downloads\vg_calc\test.py", line 49, in &lt;lambda&gt; app.dyn_combobox[i].bind('&lt;&lt;ComboboxSelected&gt;&gt;', lambda x=i: app.update_image(x)) File "C:\Users\brigh\Downloads\vg_calc\test.py", line 42, in update_image self.set_image(index) File "C:\Users\brigh\Downloads\vg_calc\test.py", line 38, in set_image self.dyn_image_path[index] = (self.cwd + '/img/heroes/' + self.dyn_combobox[index].get().lower() + '.png') TypeError: list indices must be integers or slices, not Event
  • 我的错误,bind()event 作为参数执行函数 - 你需要lambda event, x=i : app.update(x) 来获取这个event 并跳过它。
  • 完美,就像一个魅力,非常感谢你
  • 顺便说一句:如果您将从不同的文件夹运行它 - 即作为桌面上的链接/快捷方式 - 然后 os.getcwd() 为您提供桌面路径,而不是您的程序文件夹,它找不到你的文件。你必须使用self.cwd = os.path.dirname(os.path.realpath(sys.argv[0]))

标签: python user-interface tkinter ttk


【解决方案1】:

每个小部件都有 update() 方法,但是您在 App(Frame) 中创建了 update(),所以您替换它 - 它可能会产生问题。使用与update()不同的名称

【讨论】:

  • 啊,我知道这可能是个问题,谢谢你指出这一点
  • 虽然您在技术上是正确的,但与此问题无关。
  • @BryanOakley 你是什么意思?你的意思是原来的update 没有参数,但新的需要index
  • @furas:我的意思是问题仍然存在,无论该方法是否命名为 update 或其他任何名称。虽然调用它 update 可能会导致误解,但它不会影响代码的工作方式,因为代码从不尝试调用原始的内置 update 命令。
  • @BryanOakley 现在我明白了。我只用新名称对其进行了测试,它工作正常,所以我认为它解决了问题。我无法在 Linux 上重现问题 - 它总是有效。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-05-31
  • 1970-01-01
  • 2021-09-01
  • 1970-01-01
  • 2023-04-11
  • 2020-11-04
  • 1970-01-01
相关资源
最近更新 更多