【问题标题】:Remove trailing space from tkinter Text widget从 tkinter Text 小部件中删除尾随空格
【发布时间】:2021-12-07 14:06:17
【问题描述】:

我的目标是使文本框的右边缘适合文本的末尾。这在使用TkFixedFont 时会自动发生,但在使用TkDefaultFont(这是我想使用的)时,末尾会添加尾随空格。这是没有尾随空格的样子,TkFixedFont

请注意尾随空格是最小的。我想要同样的几乎没有尾随空格,但是在使用 TkDefaultFont 时。


以下是我的代码的最小示例:

from tkinter import *
root = Tk()

myText = 'sample text'

text = Text(root, bg='#c2d9ff', 
            font='TkDefaultFont',
            height=1, width=len(myText)
        )
text.insert(INSERT, myText)
text.place(x=0,y=0)
root.mainloop()

我已经搜索了大约两个小时,以查找与间距、尾随空格、小部件类型(例如标签与文本等)、小部件选项等相关的所有内容,但遗憾的是一无所获。

它似乎与文本的长度成正比,我无法弄清楚。使用上面的代码,当myText = 'Some text goes here'时,尾随间距为:

但是当我放一个较长的文本字符串时,尾随空格似乎按比例增加:

任何关于如何删除尾随空格的建议将不胜感激!

【问题讨论】:

  • 你不能使用Label吗?至于为什么会发生这种情况,可能是因为您没有使用等宽字体(例如“Courier New”或看似“TkFixedFont”),这意味着它会计算字符的平均宽度并使用它来计算空间,所以如果你只使用最宽的字符,它应该适合
  • @Matiiss 我最初使用Label,但后来改用Text,因为我需要使用标签来更改文本中字符子集的颜色。不幸的是,对我来说仍然没有意义。

标签: python tkinter tkinter-text


【解决方案1】:

您看到的不是空白字符,而是空白。实际宽度是给定字符数乘以平均大小字符中的像素数(我认为 tkinter 使用字符“0”)。在可变宽度字体中,“.”比“W”窄,因此字符串的实际宽度取决于字符串中的字符。

换句话说,如果您的文本由窄字符(例如:“............”)组成,那么如果它是由宽字符(例如: "WWWWWWWWWWWW") 会少一些。

您可以使用字体对象的measure 方法计算文本的实际宽度。一旦您确切知道您的文本字符串需要多少像素,您就可以使用该信息来适当地设置文本小部件的大小。

from tkinter import *
from tkinter.font import nametofont

root = Tk()

myText = 'sample text'
font = nametofont("TkDefaultFont")
width = font.measure(myText)

text = Text(root, bg='#c2d9ff',
            font='TkDefaultFont',
            height=1, width=len(myText)
        )
text.insert(INSERT, myText)
text.place(x=0,y=0, width=width)
root.mainloop()

请注意,当您将宽度与place 一起使用时,它指定了小部件的整个宽度,而不仅仅是边框内的宽度。您需要调整宽度以考虑文本小部件边框和突出显示的粗细,可能还需要调整一些其他像素以用于内部填充。

例如,如果文本本身占用 100 像素,并且您有一个 2 像素边框和一个用于文本小部件的 1 像素高亮环,则在调用中使用时,您需要在宽度上添加至少 6 个像素到place

【讨论】:

  • 我确实意识到这是空白空间,只是无法弄清楚。我使用了你的方法,但它并不能完全正确地计算间距。它会截断文本的最后几个字母。不过,我会弄乱字体像素大小,看看我是否能找到合适的地方。
  • measure 方法应该非常准确,只有几个像素。但是,如果您应用了可能会影响所需宽度的格式。您可能需要稍微调整宽度,因为place 中的width 是包括边框在内的总宽度。如果您的文本小部件有边框,则必须调整宽度。
【解决方案2】:

您可以使用Text.dlineinfo()获取myText占用的区域,并根据结果和其他与水平占用空间相关的设置调整text的宽度,例如:边框宽度、padx 等:

myText = 'sample text'*4

text = Text(root, bg='#c2d9ff',
            font='TkDefaultFont',
            height=1
        )
text.insert(INSERT, myText)
text.place(x=0, y=0)

text.update_idletasks() # make sure the widget is laid out completely
x, y, w, h, _ = text.dlineinfo(INSERT)
text.place(width=x+w+(text['bd']+text['padx'])*2) # adjust the width

【讨论】:

  • 感谢您的支持 — 经过一个小时的修补,我的解决方案已经完善!