【问题标题】:Tkinter Treeview doesn't give indication for hidden charactersTkinter Treeview 没有给出隐藏字符的指示
【发布时间】:2020-02-07 05:35:21
【问题描述】:

文本是“这是太长的文本”。 如您所见,视图提供了一个水平扩展选项,但没有迹象表明还有更多字符。

我需要向用户表明单元格中有更多字符。 即显示“...”。

这是代码:

from tkinter import ttk
import tkinter as tk

win = tk.Tk()
win.resizable(width=0, height=0)

tree = ttk.Treeview(win, selectmode='browse')
tree.grid(row=0, column=0)

vsb = ttk.Scrollbar(win, orient="horizontal", command=tree.xview)
vsb.grid(row=1, column=0, sticky=tk.W + tk.E + tk.N + tk.S)
tree.configure(xscrollcommand=vsb.set)

vsb = ttk.Scrollbar(win, orient="vertical", command=tree.yview)
vsb.grid(row=0, column=1, sticky=tk.W + tk.E + tk.N + tk.S)
tree.configure(yscrollcommand=vsb.set)

tree["columns"] = ("1", "2")
tree['show'] = 'headings'
tree.column("1", anchor='c')
tree.column("2", width=100, anchor='c')
tree.heading("1", text="Col 1")
tree.heading("2", text="Col 2")
tree.insert("", 'end', text="L4", values=("This text is too long","Short text"))

win.mainloop()

【问题讨论】:

  • @stovfl 我在docs.python.org/3/library/tkinter.ttk.html#treeview 文档中没有找到任何内容,你知道吗?
  • 据我所知,未实施。你必须自己做。基本捕捉.bind(<Configure>, ...width变化,根据使用的font计算列数据的width,替换column数据?
  • @stovfl ya 我认为这是要走的路。不幸的是,除非您使用等宽字体,否则它很难计算。
  • @stovfl 我不确定绑定是否可以在这里工作。仅当您更改树视图的大小而不是更改列的大小时才配置触发器。
  • @Mike-SMT:“不确定绑定是否可以在这里工作”:相关forcing-a-tkinter-ttk-treeview-widget-to-resize-after-shrinking-its-column-width

标签: python tkinter treeview


【解决方案1】:

更新:

事实证明,我们可以将'<ButtonRelease-1>' 绑定到树视图,如本文所述:@stovfl 在 cmets 中指出的how-to-detect-resizing-of-ttk-treeview-column。所以我用更少的开销更新了我的答案:D。

我创建了一个方法来检查列宽是否发生了变化,然后计算每行是否需要在末尾添加...

这是通过 PIL 中的 ImageFont 完成的,由于某种原因,认为 Treeview 字体和 PIL 字体之间存在尺寸差异。经过一些测试,您在 Treeview 样式中设置的任何字体大小似乎都只是将 5 添加到 PIL 字体中,它应该可以正确计算。

import tkinter as tk
import tkinter.ttk as ttk
from PIL import ImageFont


track_data = [[('This text is too long', 'Short text'), 'This text is too long'],
              [('This text is toooooooo long', 'Short text'), 'This text is toooooooo long'],
              [('This text is longer than most others', 'Short text'), 'This text is longer than most others'],
              [('This text is short', 'Short text'), 'This text is short']]


def add_to_tree_list(long_text, short_text, top):
    track_data.append([(long_text.get(), short_text.get()), long_text.get()])
    top.destroy()
    update_text()


def pop_list(ndex):
    track_data.pop(ndex)


def remove_row_from_list():
    top = tk.Toplevel(win)
    build_top_frame(top)
    update_text()


def build_top_frame(top):
    row_button_list = []
    for child in top.winfo_children():
        child.destroy()
    frame = tk.Frame(top)
    frame.pack()
    for ndex, sub_list in enumerate(track_data):
        row_button_list.append([tk.Button(frame, text='Remove',
                                          command=lambda n=ndex: (pop_list(n), update_text(), build_top_frame(top))),
                                tk.Label(frame, text='Row {}:  {}'.format(ndex + 1, sub_list[1]))])
        row_button_list[-1][0].grid(row=ndex, column=0)
        row_button_list[-1][1].grid(row=ndex, column=1, sticky='w')


def top_for_new_row():
    top = tk.Toplevel(win)
    tk.Label(top, text='Add long text: ').grid(row=0, column=0)
    tk.Label(top, text='Add short text: ').grid(row=1, column=0)
    e1 = tk.Entry(top)
    e2 = tk.Entry(top)
    e1.grid(row=0, column=1)
    e2.grid(row=1, column=1)
    tk.Button(top, text='Submit', command=lambda: add_to_tree_list(e1, e2, top)).grid(row=2, column=0)
    tk.Button(top, text='Cancel', command=top.destroy).grid(row=2, column=1)


def clear_and_load(data):
    tree.delete(*tree.get_children())
    for sub_list in data:
        tree.insert('''''', 'end', text='L4', values=sub_list[0])


def update_text(_=None):
    global old_col_width, old_track_data_len
    col_width = tree.column('1')['width']
    if col_width != old_col_width or old_track_data_len != len(track_data):
        old_col_width = col_width
        new_track_data = []
        for text in track_data:
            font = ImageFont.truetype("arial.ttf", 17)
            size = font.getsize(text[0][0])
            previous_long_text = ''
            new_long_text = ''
            if size[0] > col_width:
                for char in text[0][0]:
                    new_long_text = '{}{}'.format(new_long_text, char)
                    new_size = font.getsize('{}{}'.format(new_long_text, '...'))[0]
                    if new_size < col_width:
                        previous_long_text = new_long_text
                    else:
                        new_track_data.append([('{}{}'.format(previous_long_text, '...'), text[0][1]), ''])
                        break
            else:
                new_track_data.append(text)
        clear_and_load(new_track_data)
    old_track_data_len = len(track_data)


win = tk.Tk()
win.columnconfigure(0, weight=1)
old_col_width = 200
old_track_data_len = 0
win.resizable(width=0, height=0)
style = ttk.Style()
style.configure('Treeview', font=('arial', 12))
tree = ttk.Treeview(win)
tree.grid(row=0, column=0)
tree.bind('<ButtonRelease-1>', update_text)

vsb = ttk.Scrollbar(win, orient='horizontal', command=tree.xview)
vsb.grid(row=1, column=0, sticky='nsew')
tree.configure(xscrollcommand=vsb.set)

vsb = ttk.Scrollbar(win, orient='vertical', command=tree.yview)
vsb.grid(row=0, column=1, sticky='nsew')
tree.configure(yscrollcommand=vsb.set)
btn_frame = tk.Frame(win)
btn_frame.grid(row=2, column=0, columnspan=2, sticky='ew')
btn_frame.columnconfigure(0, weight=1)
btn_frame.columnconfigure(1, weight=1)
tk.Button(btn_frame, text='Add Row!', command=top_for_new_row).grid(row=0, column=0, sticky='ew')
tk.Button(btn_frame, text='Remove Row!', command=remove_row_from_list).grid(row=0, column=1, sticky='ew')

columns = ('1', '2')
tree['columns'] = columns
tree['show'] = 'headings'
tree.column('1', width=200, stretch=True, anchor='w')
tree.column('2', width=100, anchor='w')
tree.heading('1', text='Col 1')
tree.heading('2', text='Col 2')

clear_and_load(track_data)
update_text()
win.mainloop()

结果:

添加新行:

删除线:

【讨论】:

  • 一个一次事件,见how-to-detect-resizing-of-ttk-treeview-column的cmets
  • @stovfl 好好看看。摆脱了 30 行代码,现在可以在按钮释放时简单地运行我的检查。对于您的自定义树视图和我的后循环大声笑就这么多。感谢您更新我的答案的链接。
猜你喜欢
  • 2016-01-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-07-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-05-07
相关资源
最近更新 更多