更新:
事实证明,我们可以将'<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()
结果:
添加新行:
删除线: