Как получить "ширину" строки для использования в метке Tkx
Я делаю простое приложение, используя Perl Tkx и позволяю пользователю выбрать каталог. Вместо использования переноса текста или растягивания прямоугольника до нелепой длины, чтобы показать полное имя каталога, если имя слишком длинное, я бы хотел обрезать его и добавить "..." в конец.
Проблема в том, что ширина метки определяется как произвольное значение (например, 40). Если бы это значение было мерой того, сколько символов может вместить метка, я мог бы просто обрезать строку до 37 и добавить "...", но, похоже, это не так.
Кто-нибудь знает, что -width
метки с использованием Perl Tkx на самом деле является измерением? Как я могу найти сумму -width
единиц, которые займет моя строка, чтобы я мог выяснить, где подходящая точка для ее усечения?
РЕДАКТИРОВАТЬ:
Я нашел этот ответ в руководстве по tcl:
Класс базы данных: ширина Указывает желаемую ширину для метки. Если изображение или растровое изображение отображаются в метке, то значение указывается в единицах экрана (т. Е. В любой из форм, приемлемых для Tk_GetPixels); для текста это в символах.
Если этот параметр не указан, желаемая ширина метки вычисляется из размера изображения, растрового изображения или текста, отображаемого в нем.
Это должно означать, что для ширины 40, чтобы усечь текст, мне просто нужно обрезать строку до 37 символов и добавить "...".
Я проверил это, заполнив этикетку всеми буквами "М". Я использовал букву "М", потому что это обычно самый широкий символ ( см. Здесь). Я написал код для усечения с 37 "M" и добавил "..." в конец, но, похоже, "M" переполняются после конца метки примерно через 24 "M".
Это означает, что небезопасно предполагать, что он просто растягивает ярлык до 40 самых широких символов... поэтому мой вопрос до сих пор остается без ответа.
Как я могу определить "ширину" моей строки, чтобы я мог усечь ее соответствующим образом?
EDIT2:
Я нашел обходной путь, но это все еще не решение, которое я искал. Если вы измените текст на этикетке на шрифт фиксированной ширины, он будет работать правильно. Хотя это выглядит не так хорошо, поэтому мне бы очень хотелось, чтобы решение работало для шрифтов не фиксированной ширины.
1 ответ
Когда документы говорят, что -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;
}