如何获取要在 Tkx 标签中使用的字符串的 "width"

How to get the "width" of a string to be used in a Tkx label

我正在使用 Perl Tkx 制作一个简单的应用程序并允许用户 select 一个目录。如果名称太长,我不想使用文本换行或将框拉伸到荒谬的长度来显示整个目录名称,而是截断它并在末尾附加“...”。

问题是标签的宽度被定义为某个任意值(如 40)。如果这个值是标签可以容纳多少个字符的度量,我可以将字符串截断为 37 并附加“...”,但情况似乎并非如此。

有谁知道使用 Perl Tkx 的标签的 -width 实际上是衡量什么的?我怎样才能找到我的字符串将占用的 -width 个单位的数量,以便我可以找出适当的点来截断它?


编辑:

我在 tcl manual 中找到了这个答案:

Database Class: Width Specifies a desired width for the label. If an image or bitmap is being displayed in the label then the value is in screen units (i.e. any of the forms acceptable to Tk_GetPixels); for text it is in characters.

If this option isn't specified, the label's desired width is computed from the size of the image or bitmap or text being displayed in it.

这应该意味着要截断文本的宽度为 40,我应该只需要将字符串截断为 37 个字符并添加“...”。

我通过用所有 "M" 填充标签来测试这个。我使用字母 "M" 因为它通常是最宽的字符 (see here)。我编写了代码以在 37 "M"s 处截断并在末尾添加“...”,但是 "M"s 似乎在大约 24 "M"s 后溢出了标签的末尾.

这意味着假设它只是拉伸标签以适应 40 个最宽的字符是不安全的...因此我的问题仍然没有答案。

如何确定字符串的 "width" 以便适当截断它?


EDIT2:

我找到了解决方法,但它仍然不是我正在寻找的解决方案。如果将标签上的文本更改为固定宽度的字体,它将正常工作。虽然它看起来不太好,但我真的很想要一个适用于非固定宽度字体的解决方案。

当文档说标签的 -width 被解释为多个字符时,它可能使用字符的平均宽度而不是最大宽度。正如您所发现的,当使用固定宽度的字体时,您可以在字符中工作并且一切都会很好地出现。当使用可变宽度字体时,事情很快就会变得困难,因为字符和像素之间没有固定的关系。

您需要以一致的单位(即像素)工作并缩短文本直到适合 - 最好有一个很好的初始猜测以保持您的代码快速。您可以通过 winfo reqwidth 获取以像素为单位的标签宽度,并使用 font measure.

获取以像素为单位的文本宽度(对于特定字体)
use strict;
use warnings;
use Tkx;
Tkx::package_require('tile');

my $text;
my $mw    = Tkx::widget->new('.');
my $label = $mw->new_ttk__label(-width => 10, -textvariable => $text);

Tkx::pack($label, -side => 'left');

$text = limit_text($label, 'abcdefghijklmnopqrstuvwxyz');

Tkx::MainLoop;

sub limit_text {
    my $label       = shift;
    my $text        = shift;
    my $font        = $label->cget('-font') || 'TkDefaultFont';
    my $label_width = $label->g_winfo_reqwidth;
    my $text_width  = Tkx::font_measure($font, $text);
    my $i           = int length($text) * ($label_width / $text_width);

    while ($text_width > $label_width) {
        $text       = substr($text, 0, --$i) . '...';
        $text_width = Tkx::font_measure($font, $text);
    }
    return $text;
}