繁体   English   中英

Tkinter,如何调整 treeview 压痕大小和指示箭头图像

[英]Tkinter, how to adjust treeview indentation size and indicator arrow image

我有一个 treeview 小部件,您可以放大和缩小字体大小。 问题是缩进在放大时与正常时不成比例。 有没有办法调整压痕宽度? 下面是两张图片,一张是正常的,另一张是放大的。 我也想知道是否有办法改变指标图像?

更新:感谢下面的jasonharper评论,我已经解决了缩进问题。 我仍然需要更改指示箭头图像似乎在 web 上找不到任何信息。

图像1

图2

缩进

正如 jasonharper 和 Daniel Huckson 在评论中所说,缩进可以改变

style.configure('Treeview', indent=100)

指标图像

可以通过创建自定义主题元素并使用它来替换Treeview.Item布局中的标准指标来更改指标图像。

这里的关键是要知道打开的项目('user1')和没有孩子的项目('user2')的状态名称,关闭是默认的 state。 因此,打开指示器需要与 state ('user1', '!user2')中的项目和空图像映射到 state ('user2', )中的项目。

我使用 PIL 为指标创建虚拟图像,但可以直接加载自定义图像。

from PIL import Image, ImageTk, ImageDraw
import tkinter as tk
from tkinter import ttk

root = tk.Tk()

style = ttk.Style(root)

# custom indicator images
im_open = Image.new('RGBA', (15, 15), '#00000000')
im_empty = Image.new('RGBA', (15, 15), '#00000000')
draw = ImageDraw.Draw(im_open)
draw.polygon([(0, 4), (14, 4), (7, 11)], fill='yellow', outline='black')
im_close= im_open.rotate(90)

img_open = ImageTk.PhotoImage(im_open, name='img_open', master=root)
img_close = ImageTk.PhotoImage(im_close, name='img_close', master=root)
img_empty = ImageTk.PhotoImage(im_empty, name='img_empty', master=root)

# custom indicator
style.element_create('Treeitem.myindicator',
                     'image', 'img_close', ('user1', '!user2', 'img_open'), ('user2', 'img_empty'),
                     sticky='w', width=15)
# replace Treeitem.indicator by custom one
style.layout('Treeview.Item',
[('Treeitem.padding',
  {'sticky': 'nswe',
   'children': [('Treeitem.myindicator', {'side': 'left', 'sticky': ''}),
    ('Treeitem.image', {'side': 'left', 'sticky': ''}),
    ('Treeitem.focus',
     {'side': 'left',
      'sticky': '',
      'children': [('Treeitem.text', {'side': 'left', 'sticky': ''})]})]})]
)


tree = ttk.Treeview(root)
tree.pack()
tree.insert('', 'end', text='item 1', open=True)
tree.insert('', 'end', text='item 2')
tree.insert('I001', 'end', text='item 11', open=False)
tree.insert('I001', 'end', text='item 12', open=False)
tree.insert('I004', 'end', text='item 121', open=False)

root.mainloop()

截屏

我接受了接受的答案并调整了代码。 通过使用 treeview 行高作为参数自动计算多边形坐标,它更短更稳健。

    ''' Create images for open, close and empty '''
    width = row_height-7

    im_open, im_close, im_empty = triangle_raw_images(width, 
                                                'black', 'LightGrey')
    img_open = ImageTk.PhotoImage(im_open)
    img_close = ImageTk.PhotoImage(im_close)
    img_empty = ImageTk.PhotoImage(im_empty)

    # custom indicator
    style.element_create('Treeitem.myindicator', 'image', img_close,
                    ('user1', '!user2', img_open), ('user2', img_empty), 
                    sticky='w', width=width)

    # replace Treeitem.indicator by custom one
    style.layout('Treeview.Item',
    [('Treeitem.padding',
      {'sticky': 'nswe',
       'children': [
            ('Treeitem.myindicator', {'side': 'left', 'sticky': ''}),
            ('Treeitem.image', {'side': 'left', 'sticky': ''}),
            ('Treeitem.focus', {'side': 'left', 'sticky': '','children':
                                    [('Treeitem.text', 
                                      {'side': 'left','sticky': ''})]
                               })
                  ]
       })])

以上来自已接受答案的更改:

  • row_height与传递给 treeview 的变量相同,当使用较大的字体大小时,HiDPI 屏幕需要该变量。
  • 使用变量名而不是指向变量的指针,从而缩短了一些行。 例如ImageTk.PhotoImage(im_open)用于代替ImageTk.PhotoImage(im_open, name='img_open', master=root)
  • 换行以遵守 PEP 标准 79 字符行长度
  • 缩进右括号以希望使代码更具可读性。

变化的核心是新的 function:

def triangle_raw_images(hgt, outc, fillc):

    from PIL import Image, ImageTk, ImageDraw       # Pillow image processing

    # For comments in code assume passed hgt = 21
    wid = hgt                                       # square image
    hgt_off = 4                                     # top & bottom whitespace
    wxy = ( 0, hgt_off, )                           # west point x=0, y=4
    exy = ( wid-1, hgt_off, )                       # east point x=20, y=4
    sxy = ( int((hgt-1)/2), hgt-hgt_off, )          # south point x=10, y=17
    retn_images = []                                # list of three images

    # custom indicator images
    im_open = Image.new('RGBA', (wid, hgt), (0, 0, 0, 0))
    im_empty = Image.new('RGBA', (wid, hgt), (0, 0, 0, 0))
    draw = ImageDraw.Draw(im_open)
    draw.polygon([ wxy, exy, sxy ], outline=outc, fill=fillc)
    im_close= im_open.rotate(90)

    return im_open, im_close, im_empty

这是最终结果:

mserve open close triangles.png

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM