我的窗口上有一些小部件。标签lb3随着我的窗口扩大。我想从长数组中放入一些字符。因此,如果窗口很大,则必须有更多字符,如果窗口的大小较小,则字符数会更少。 因此,我需要以字符为单位了解Label的当前高度和宽度。 我的问题有一个例子:
import Tkinter as tk
import tkFont
import sys
import os
last_event_H = 0
last_event_W = 0
LONG_ARRAY = ''
# when window sized
def sizing(event):
global last_event_H
global last_event_W
global LONG_ARRAY
if (event.width == last_event_W and event.height == last_event_H):
return
last_event_H = event.height
last_event_W = event.width
width_in_chars = lb3['width']
height_in_chars = lb3['height']
first_shown = int(lb1_text.get())
lb3_text.set(LONG_ARRAY[first_shown:first_shown + width_in_chars * height_in_chars])
lb2_text.set(LONG_ARRAY[first_shown + width_in_chars * height_in_chars] + ' ...')
class WrappingLabel(tk.Label):
'''a type of Label that automatically adjusts the wrap to the size'''
def __init__(self, master=None, **kwargs):
tk.Label.__init__(self, master, **kwargs)
self.bind('<Configure>', lambda e: self.config(wraplength=self.winfo_width()))
if __name__ == '__main__':
root = tk.Tk()
root.geometry("1280x640")
dFont=tkFont.Font(family="Arial", size=30) # fixed Font
LONG_ARRAY = 'a' * 100000 # of symbols
tb_date = tk.Entry(root, font=dFont)
tb_date.grid(column=0, row=0, columnspan=3, sticky=tk.NSEW)
bt_find = tk.Button(root, text="...", font=dFont)
bt_find.grid(column=9, row=0, columnspan=2, sticky=tk.NSEW)
lb1_text = tk.StringVar()
lb1_text.set("1")
lb1 = tk.Label(root, textvariable=lb1_text, width=10, font=dFont, anchor=tk.NW)
lb1.grid(column=0, row=1, sticky=tk.NSEW)
lb2_text = tk.StringVar()
lb2 = tk.Label(root, textvariable=lb2_text, width=10, font=dFont, anchor=tk.NW)
lb2.grid(column=1, row=10, columnspan=9, sticky=tk.NSEW)
lb3_text = tk.StringVar()
lb3 = WrappingLabel(root, textvariable=lb3_text, font=dFont, anchor=tk.NW, justify=tk.LEFT)
lb3.grid(column=1, row=1, columnspan=9, rowspan=9, sticky=tk.NSEW)
for x in range(11):
tk.Grid.columnconfigure(root, x, weight=1)
for y in range(11):
tk.Grid.rowconfigure(root, y, weight=1)
root.bind("<Configure>", sizing)
width_in_chars = lb3['width']
height_in_chars = lb3['height']
print width_in_chars, height_in_chars # !!!!!!!!!!!!!
print "-------"
lb3_text.set(LONG_ARRAY[:width_in_chars * height_in_chars])
lb2_text.set(LONG_ARRAY[width_in_chars * height_in_chars] + ' ...') # last shown character
root.mainloop()
现在将lb3的width和height成员设置为0。 因为它能够扩展。还有另一种方法吗?
答案 0 :(得分:1)
如果您想确切知道可以容纳多少个字符,则要做的第一件事就是获取标签的大小。这需要在小部件显示后发生,因为直到它发生之前,它的宽度是未知的。您可以通过调用winfo_reqwidth
事先完成此操作,尽管该数字可能大于或小于实际宽度,具体取决于您在pack
,place
或grid
中使用的选项
一旦知道最大大小,就可以使用字体对象的font_measure
方法来计算字符串中的像素数。然后,只需编写一个循环即可找出适合的最大字符数。
可以在此答案中找到一个示例,该示例演示如何为太长的标签动态添加“ ...”:https://stackoverflow.com/a/51144251/7432
答案 1 :(得分:0)
感谢@BryanOakley提供有用的链接
问题的我的解决方案版本 (如果有人可以做得更好,请回复)
import Tkinter as tk
import tkFont
import sys
import os
import bisect
LONG_ARRAY = ''
class KeyList(object):
# bisect doesn't accept a key function, so we build the key into our sequence.
def __init__(self, l, key):
self.l = l
self.key = key
def __len__(self):
return len(self.l)
def __getitem__(self, index):
return self.key(self.l[index], index)
class WrappingLabel(tk.Label):
'''a type of Label that automatically adjusts the wrap to the size'''
def __init__(self, master=None, **kwargs):
tk.Label.__init__(self, master, **kwargs)
self.bind('<Configure>', self.fit)
if (not hasattr(self, "original_text")):
# preserve the original text so we can restore it if the widget grows.
self.original_text = self["text"]
self.font = tkFont.nametofont(self["font"])
self.font_height = 48.88 # self.font.metrics('linespace')
def fit(self, event):
max_width = event.width
max_height = event.height / self.font_height # rough n_lines
text = LONG_ARRAY[:2000] # TODO !!! self.original_text
actual_width = self.font.measure(text)
if (actual_width > max_width * max_height):
# the original text won't fit. Keep shrinking until it does
i = bisect.bisect_left(KeyList(text, key=lambda x,i: self.font.measure(text[:i]+ '...')), max_width * max_height)
lb3_text.set(text[:i] + '...') # TODO !!! self.original_text
return self.config(wraplength=self.winfo_width())
if __name__ == '__main__':
root = tk.Tk()
root.geometry("1280x640")
dFont=tkFont.Font(family="Arial", size=30) # fixed Font
LONG_ARRAY = 'a' * 100000 # of symbols
root.grid_columnconfigure(0, weight=1)
frame = tk.Frame(root)
tk.Grid.rowconfigure(root, 0, weight=1)
tk.Grid.columnconfigure(root, 0, weight=1)
frame.grid(row=0, column=0, sticky=tk.NSEW)
tb_date = tk.Entry(frame, font=dFont)
tb_date.grid(column=0, row=0, columnspan=3, sticky=tk.NSEW)
bt_find = tk.Button(frame, text="...", font=dFont)
bt_find.grid(column=9, row=0, columnspan=2, sticky=tk.NSEW)
lb1_text = tk.StringVar()
lb1_text.set("1")
lb1 = tk.Label(frame, textvariable=lb1_text, width=10, font=dFont, anchor=tk.NW)
lb1.grid(column=0, row=1, sticky=tk.NSEW)
lb3_text = tk.StringVar()
lb3 = WrappingLabel(frame, textvariable=lb3_text, font=dFont, anchor=tk.NW, justify=tk.LEFT)
#lb3 = tk.Text(frame, font=dFont, state=tk.DISABLED, wrap=tk.CHAR) # bg=frame["bg"], fg='black',
lb3.grid(column=1, row=1, rowspan=2, columnspan=9, sticky=tk.NSEW)
lb2_text = tk.StringVar()
lb2 = tk.Label(frame, textvariable=lb2_text, width=10, font=dFont, anchor=tk.NW)
lb2.grid(column=1, row=4, columnspan=9, rowspan=2, sticky=tk.NSEW)
lb2_text.set('................................................')
for y in range(11):
tk.Grid.columnconfigure(frame, y, weight=1)
for x in range(5):
tk.Grid.rowconfigure(frame, x, weight=1)
lb3_text.set(LONG_ARRAY[:2000])
#lb3.insert(tk.INSERT, LONG_ARRAY[:2000])
#lb3.insert(tk.END, "")
root.mainloop()