将tkinter图像嵌入到Toplevel中

时间:2018-01-11 22:48:31

标签: python oop tkinter

我想将图片添加到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)

2 个答案:

答案 0 :(得分:1)

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

在新方法中,它创建并保存 SideMenu实例。在您的代码中,该实例几乎在创建时就被删除,因为它没有存储在变量中。我也对tk.PhotoImage个实例进行了类似的操作 - 即使它对于MainMenu中的实例也不是绝对必要的,因为在tk.mainloop()末尾的launch_MainMenu()调用它可以防止它所处的局部变量过早地超出范围(所以当它仍然需要时它不会被删除)。无论如何我都是这样做的,因为tkinter中使用的所有图像通常都是很好用的(人们不这样做的原因很大一部分原因在于#&} 39;这里有很多相关的问题。)

我还尝试重新格式化您的代码,使其更紧密地跟随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()

答案 1 :(得分:1)

问题是由于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)
        ...