使用 tkinter 将文本放入矩形(宽度 x x 高度 y)
Fitting text into a rectangle (width x by height y) with tkinter
我正在尝试制作一个程序,根据文本、字体和字体大小将文本放入一个矩形(x x y)中
这是代码
def fit_text(screen, width, height, text, font):
measure_frame = Frame(screen) # frame
measure_frame.pack()
measure_frame.pack_forget()
measure = Label(measure_frame, font = font) # make a blank label
measure.grid(row = 0, column = 0) # put it in the frame
##########################################################
# make a certain number of lines
##########################################################
words = text.split(" ")
lines = []
num = 0
previous = 0
while num <= len(words):
measure.config(text = " ".join(words[previous:num])) # change text
line_width = measure.winfo_width() # get the width
print(line_width)
if line_width >= width: # if the line is now too long
lines.append(" ".join(words[previous:num - 1])) # add the last vsion which wasn't too long
previous = num - 1 # previous is now different
num = num + 1 # next word
lines.append(" ".join(words[previous:])) # add the rest of it
return "\n".join(lines)
from tkinter import *
window = Tk()
screen = Canvas(window)
screen.pack()
text = fit_text(screen, 200, 80, "i want to fit this text into a rectangle which is 200 pixels by 80 pixels", ("Purisa", 12))
screen.create_rectangle(100, 100, 300, 180)
screen.create_text(105, 105, text = text, font = ("Purisa", 12), anchor = "nw")
这个问题是无论标签中的文本是什么,measure.winfo_width()
的结果总是 1。Here is where I found this from 但它似乎对我不起作用
小部件在打包之前不会有宽度。你需要把标签放进相框里,然后打包,然后算了。
您的代码的问题是您使用的是小部件的宽度,但在小部件实际布置在屏幕上并使其可见之前宽度将为 1,因为实际宽度取决于一个数字在这种情况发生之前不存在的因素。
您无需将文本放入小部件中即可对其进行测量。您可以将字符串传递给 font.measure()
,它将 return 以给定字体呈现该字符串所需的 space 数量。
对于 python 3.x,您可以像这样导入 Font
class:
from tkinter.font import Font
对于 python 2.x 你从 tkFont
模块导入它:
from tkFont import Font
然后您可以创建 Font
的实例,以便您可以获得有关该字体的信息:
font = Font(family="Purisa", size=18)
length = font.measure("Hello, world")
print "result:", length
您还可以使用 font.metrics()
方法获取给定字体的行高,为其提供参数 "linespace":
height = font.metrics("linespace")
我实际上是通过反复试验偶然发现了一种方法
通过使用 measure.update_idletasks()
它可以正确计算宽度并且可以正常工作! Bryan Oakley 肯定有更有效的方法,但我认为这种方法在其他情况下会有用
P.S。我不介意一些选票来获得一个漂亮的、闪亮的、青铜色的自学者徽章 ;)
我正在尝试制作一个程序,根据文本、字体和字体大小将文本放入一个矩形(x x y)中
这是代码
def fit_text(screen, width, height, text, font):
measure_frame = Frame(screen) # frame
measure_frame.pack()
measure_frame.pack_forget()
measure = Label(measure_frame, font = font) # make a blank label
measure.grid(row = 0, column = 0) # put it in the frame
##########################################################
# make a certain number of lines
##########################################################
words = text.split(" ")
lines = []
num = 0
previous = 0
while num <= len(words):
measure.config(text = " ".join(words[previous:num])) # change text
line_width = measure.winfo_width() # get the width
print(line_width)
if line_width >= width: # if the line is now too long
lines.append(" ".join(words[previous:num - 1])) # add the last vsion which wasn't too long
previous = num - 1 # previous is now different
num = num + 1 # next word
lines.append(" ".join(words[previous:])) # add the rest of it
return "\n".join(lines)
from tkinter import *
window = Tk()
screen = Canvas(window)
screen.pack()
text = fit_text(screen, 200, 80, "i want to fit this text into a rectangle which is 200 pixels by 80 pixels", ("Purisa", 12))
screen.create_rectangle(100, 100, 300, 180)
screen.create_text(105, 105, text = text, font = ("Purisa", 12), anchor = "nw")
这个问题是无论标签中的文本是什么,measure.winfo_width()
的结果总是 1。Here is where I found this from 但它似乎对我不起作用
小部件在打包之前不会有宽度。你需要把标签放进相框里,然后打包,然后算了。
您的代码的问题是您使用的是小部件的宽度,但在小部件实际布置在屏幕上并使其可见之前宽度将为 1,因为实际宽度取决于一个数字在这种情况发生之前不存在的因素。
您无需将文本放入小部件中即可对其进行测量。您可以将字符串传递给 font.measure()
,它将 return 以给定字体呈现该字符串所需的 space 数量。
对于 python 3.x,您可以像这样导入 Font
class:
from tkinter.font import Font
对于 python 2.x 你从 tkFont
模块导入它:
from tkFont import Font
然后您可以创建 Font
的实例,以便您可以获得有关该字体的信息:
font = Font(family="Purisa", size=18)
length = font.measure("Hello, world")
print "result:", length
您还可以使用 font.metrics()
方法获取给定字体的行高,为其提供参数 "linespace":
height = font.metrics("linespace")
我实际上是通过反复试验偶然发现了一种方法
通过使用 measure.update_idletasks()
它可以正确计算宽度并且可以正常工作! Bryan Oakley 肯定有更有效的方法,但我认为这种方法在其他情况下会有用
P.S。我不介意一些选票来获得一个漂亮的、闪亮的、青铜色的自学者徽章 ;)