将 tkinter 图像嵌入到顶层

Posted

技术标签:

【中文标题】将 tkinter 图像嵌入到顶层【英文标题】:Embedding a tkinter image into a Toplevel 【发布时间】:2018-06-21 08:56:49 【问题描述】:

我想在tkinter 的顶框中添加一张图片。它适用于MainMenu,但不适用于SideMenu。运行时,它应该在第一个菜单上显示_test.gif,当按下按钮时,打开第二个菜单并显示_test2.gif。目前,第二个菜单是空白的 - 没有图像。

代码:

import tkinter as tk

class MainMenu(object):
    def __init__(self):
        self.launch_MainMenu()
    def launch_MainMenu(self):
        self._mainMenuWindow = tk.Tk()
        self.imageGIF = tk.PhotoImage(file="_test.gif");
        self.imageLabel = tk.Label(self._mainMenuWindow,image=self.imageGIF)
        self.imageLabel.grid(row=0,column=1,padx=10,pady=10)
        tk.Button(self._mainMenuWindow,text="Next Menu",
                  command=SideMenu).grid(row=0,column=2,padx=10)
        tk.mainloop()

class SideMenu(object):
    def __init__(self):
        self.launch_sideMenu()
    def launch_sideMenu(self):
        self._sideWindow = tk.Toplevel()
        self.imageGIF2 = tk.PhotoImage(file="_test2.gif")
        self.imageLabel2 = tk.Label(self._sideWindow,image=self.imageGIF2)
        self.imageLabel2.grid(row=0,column=1,padx=10,pady=10)

【问题讨论】:

此adding image to tkinter gui 将对您的问题有所帮助。您将需要添加“自我”。在局部变量(imageXxx)之前。 @kunif:一开始我也是这么想的,但这不是这里的问题。 抱歉,我过度简化了我的原始代码。这是 2 张不同的图片。 MainMenu 类的变量前面没有“self.”。而且,initialie Tk() 和 mainloop 放在 MainMenu 类之外会更好吗? . 感谢您的建议 kunif。我已经添加了自我。到主菜单中的所有内容,但第二张图像仍未显示。请问您能提供更多帮助吗? 【参考方案1】:

以下更改将使其工作。一个名为add_sidemenu() 的新方法已添加到类MainMenu 中,并在创建Button 小部件时用作command= 参数的值。

在新方法中,它创建并保存一个SideMenu 实例。在您的代码中,这个实例几乎一被创建就被删除,因为它没有存储在变量中。我还对两个tk.PhotoImage 实例做了类似的事情——即使对于MainMenu 中的实例来说,这并不是绝对必要的,因为launch_MainMenu() 末尾的tk.mainloop() 调用可以防止它所在的局部变量超出范围太快了(所以它在仍然需要时不会被删除)。无论如何,我还是这样做了,因为使用tkinter 中使用的 all 图像通常是一个很好的做法(人们不这样做是这里有这么多相关问题的主要原因)。

我还尝试重新格式化您的代码,使其更接近PEP 8 - Style Guide for Python Code。我强烈建议您阅读并开始遵循以下指南——您的代码将更易于其他人(和您)阅读(以及简化调试和维护)。

import tkinter as tk

class MainMenu(object):
    def __init__(self):
        self.launch_MainMenu()

    def launch_MainMenu(self):
        self._mainMenuWindow = tk.Tk()
        self.imageGIF = tk.PhotoImage(file="_test.gif");
        imageLabel = tk.Label(self._mainMenuWindow, image=self.imageGIF)
        imageLabel.grid(row=0, column=1, padx=10, pady=10)
        tk.Button(self._mainMenuWindow, text="Next Menu",
                  command=self.add_sidemenu).grid(row=0, column=2, padx=10)
        tk.mainloop()

    def add_sidemenu(self):
        self.sidemanu = SideMenu()
        self.sidemanu.grid(row=0, column=2, padx=10)

class SideMenu(object):
    def __init__(self):
        self.launch_sideMenu()

    def launch_sideMenu(self):
        self._sideWindow = tk.Toplevel()
        self.imageGIF2 = tk.PhotoImage(file="_test2.gif")
        self.imageLabel2 = tk.Label(self._sideWindow, image=self.imageGIF2)
        self.imageLabel2.grid(row=0, column=1, padx=10, pady=10)

mainMenu = MainMenu()

【讨论】:

这太棒了,非常感谢您过来帮助我。我正在制作的程序是为了帮助其他真正需要它的人,而我又回到了完成它的路上!祝你有美好的一天!【参考方案2】:

问题是由于 python 的垃圾收集器造成的。您没有保留对 SideMenu 实例的引用,因此它正在被垃圾收集。

由于 tkinter 实现方式的怪异,即使小部件本身没有被破坏,也会导致图像对象被破坏。

高度不寻常地将按钮的目标设为一个类。相反,创建一个适当的函数来创建SideMenu 的实例,并保存对该对象的引用。

class MainMenu(object):
    ...
    def launch_ManMenu(self):
        ...
        tk.Button(..., command=self.sidemenu, ...)

    def sidemenu(self):
        self.sidemenu = SideMenu()

您还需要在SideMenu 中保留图像的引用,就像在MainMenu 中一样:

class SideMenu(object):
    ...
    def launch_sideMenu(self):
        ...
        self.my_image = tk.PhotoImage(...)
        myCanvas.create_image(..., image=self.my_image)
        ...

【讨论】:

这太棒了,非常感谢您过来帮助我。我正在制作的程序是为了帮助其他真正需要它的人,而我又回到了完成它的路上!祝你有美好的一天!我真希望我也能在这个答案上打勾!

以上是关于将 tkinter 图像嵌入到顶层的主要内容,如果未能解决你的问题,请参考以下文章

使用 PIL 在 Tkinter Canvas 小部件中嵌入图像

将 matplotlib 动画嵌入到 tkinter 帧中

Tkinter GUI 中实时更新的 Blitting - 性能和图像重叠问题

如何将 python tkinter 窗口嵌入浏览器?

将matplotlib嵌入到tkinter画布中会打开两个窗口

如何将 tkinter 表保存为图像