【问题标题】:tkinter.ttk.Treeview root node icon/image does not appeartkinter.ttk.Treeview 根节点图标/图像不出现
【发布时间】:2016-06-01 01:23:11
【问题描述】:

问题:我无法在 tkinter.ttk.Treeview 的根节点旁边显示图标图像。下面是我使用的测试代码。它执行时没有错误,但图像没有出现在根节点的左侧。我尝试使用图像文件的完整路径名,但没有奏效。另外,我尝试使用 PIL.ImageTk.PhotoImage 打开图像文件,但这也不起作用。而是出现了如下所示的错误。

问题:如何让图标图像出现在 tkinter.ttk.Treeview 的根节点(或任何节点)的左侧?

测试代码:

import os
import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk

class App(ttk.Frame):

    def __init__(self, master, path):
    ttk.Frame.__init__(self, master)
    self.tree = ttk.Treeview(self)
    ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
    xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
    self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
    self.tree.heading('#0', text='Directory', anchor='w')

    abspath = os.path.abspath(path)
    i = './icon/Home-icon_16.gif'
    root_pic = tk.PhotoImage(file=i)
    #root_pic = ImageTk.PhotoImage(i)
    root_node = self.tree.insert('', 'end', text=abspath, open=True, image=root_pic)
    l1_node = self.tree.insert(root_node, 'end', text='level 1', open=True)
    l2_node = self.tree.insert(l1_node, 'end', text='level 2', open=True)
    l3_node = self.tree.insert(l2_node, 'end', text='level 3', open=True)
    l2a_node = self.tree.insert(l1_node, 'end', text='level 2a', open=True)
    l3a_node = self.tree.insert(l2a_node, 'end', text='level 3a', open=True)

    self.tree.grid(row=0, column=0)
    ysb.grid(row=0, column=1, sticky='ns')
    xsb.grid(row=1, column=0, sticky='ew')
    self.grid()

root = tk.Tk()
path_to_my_project = os.getcwd()
app = App(root, path=path_to_my_project)
app.mainloop()

使用 PIL.ImageTk.PhotoImage 时出错消息:

root_pic = ImageTk.PhotoImage(i)
  File "/usr/lib/python3/dist-packages/PIL/ImageTk.py", line 108, in __init__
    mode = Image.getmodebase(mode)
  File "/usr/lib/python3/dist-packages/PIL/Image.py", line 296, in getmodebase
    return ImageMode.getmode(mode).basemode
  File "/usr/lib/python3/dist-packages/PIL/ImageMode.py", line 52, in getmode
    return _modes[mode]
KeyError: './icon/Home-icon_16.gif'

Home-icon_16.gif

应用: python3.5 ver3.5.1-10; python3-tk ver3.5.1-1; tk8.6 版本 8.6.5-1; python3-pil.imagetk:amd64 ver3.1.2-0ubuntu1

【问题讨论】:

  • 您发布的错误与代码不匹配。错误显示语句root_pic = ImageTk.PhotoImage(i),但代码显示root_pic = ImageTk.PhotoImage(file=i)
  • Bryan,错误与我的代码匹配。当我取消注释 #root_pic = ImageTk.PhotoImage(i) 并注释 root_pic = tk.PhotoImage(file=i) 时发生错误。正如我在问题陈述中提到的,我尝试了两种方法。 root_pic = tk.PhotoImage(file=i) 执行没有错误。但是 root_pic = ImageTk.PhotoImage(i) 方法显示了我上面报告的错误。我从下面 Stevo 的回答中了解到,缺少的是“自我”的使用。在图像的实例名称之前。通过这样做,它创建了对图像的引用,我认为克服了一个 tk 错误。

标签: image python-3.x treeview python-imaging-library ttk


【解决方案1】:

尝试先使用Image.open('file_path') 创建 PIL 映像,然后再使用Photoimage。此外,您需要保留对 PhotoImage 的引用,否则它不会在 tkinter 中显示。

import os
import tkinter as tk
import tkinter.ttk as ttk
from PIL import Image, ImageTk

class App(ttk.Frame):

    def __init__(self, master, path):
        ttk.Frame.__init__(self, master)
        self.tree = ttk.Treeview(self)
        ysb = ttk.Scrollbar(self, orient='vertical', command=self.tree.yview)
        xsb = ttk.Scrollbar(self, orient='horizontal', command=self.tree.xview)
        self.tree.configure(yscroll=ysb.set, xscroll=xsb.set)
        self.tree.heading('#0', text='Directory', anchor='w')

        abspath = os.path.abspath(path)
        i = './icon/Home-icon_16.gif'
        root_pic1 = Image.open(i)                           # Open the image like this first
        self.root_pic2 = ImageTk.PhotoImage(root_pic1)      # Then with PhotoImage. NOTE: self.root_pic2 =     and not     root_pic2 =

        root_node = self.tree.insert('', 'end', text=abspath, open=True, image=self.root_pic2)
        l1_node = self.tree.insert(root_node, 'end', text='level 1', open=True)
        l2_node = self.tree.insert(l1_node, 'end', text='level 2', open=True)
        l3_node = self.tree.insert(l2_node, 'end', text='level 3', open=True)
        l2a_node = self.tree.insert(l1_node, 'end', text='level 2a', open=True)
        l3a_node = self.tree.insert(l2a_node, 'end', text='level 3a', open=True)

        self.tree.grid(row=0, column=0)
        ysb.grid(row=0, column=1, sticky='ns')
        xsb.grid(row=1, column=0, sticky='ew')
        self.grid()

root = tk.Tk()
path_to_my_project = os.getcwd()
app = App(root, path=path_to_my_project)
app.mainloop()

【讨论】:

  • 谢谢史蒂夫。所以简单地放一个“自我”。在图像实例名称之前,即“self.root_pic1”将起作用。问题。主页图像已经出现,但它没有取代用于切换节点打开和关闭状态的默认箭头符号。为什么会这样?我曾假设在 .insert() 方法中使用 image 关键字将替换默认箭头。你能告诉他如何做到这一点吗?
  • Stevo,我认为将我的问题作为一个新问题发布更合适,因为这是一个不同的问题。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 1970-01-01
  • 2013-11-20
相关资源
最近更新 更多