将 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 小部件中嵌入图像
Tkinter GUI 中实时更新的 Blitting - 性能和图像重叠问题