Создавайте изменяемые по размеру/многострочные метки Tkinter/ttk с переносом слов

Можно ли создать многострочную метку с переносом слов, размер которой изменяется синхронно с шириной ее родителя? Другими словами, поведение переноса слов Блокнота при изменении ширины окна Блокнота.

Вариант использования — это диалоговое окно, в котором необходимо представить блок многострочного текста (инструкции) полностью, не обрезая текст и не прибегая к полосам прокрутки. В родительском контейнере будет достаточно места по вертикали, чтобы вместить узкую ширину.

Я безуспешно экспериментировал с виджетами Tkinter Label и Message, а также с виджетом ttk Label. Кажется, мне нужно жестко закодировать значение длины переноса в пикселях, а не сделать так, чтобы эти элементы управления автоматически переносили слова, когда их текст достигает правого края их контейнеров. Конечно, менеджеры геометрии Tkinters могут помочь мне автоматически изменить размер моих меток и соответствующим образом обновить их значения длины переноса?

Должен ли я вместо этого смотреть на виджет «Текст»? Если да, то можно ли скрыть границу текстового виджета, чтобы я мог использовать его как многострочную метку с переносом слов?

Вот прототип того, как можно сделать то, что я описал выше. Он был вдохновлен советом Брайана Окли по использованию виджета «Текст» и следующей публикацией в Stackoverflow: a-label-such-that-you-can-select-the-text-wit">В tkinter Python, как я могу сделать метку, чтобы вы могли выбирать текст с помощью мыши?

from Tkinter import *
master = Tk()

text = """
If tkinter is 8.5 or above you'll want the selection background to appear like it does when the widget is activated. Comment this out for older versions of Tkinter.

This is even more text.

The final line of our auto-wrapping label that supports clipboard copy.
""".strip()

frameLabel = Frame( master, padx=20, pady=20 )
frameLabel.pack()
w = Text( frameLabel, wrap='word', font='Arial 12 italic' )
w.insert( 1.0, text )
w.pack()

# - have selection background appear like it does when the widget is activated (Tkinter 8.5+)
# - have label background color match its parent background color via .cget('bg')
# - set relief='flat' to hide Text control borders
# - set state='disabled' to block changes to text (while still allowing selection/clipboard copy)
w.configure( bg=master.cget('bg'), relief='flat', state='disabled' )

mainloop()

person Malcolm    schedule 25.10.2010    source источник


Ответы (4)


Нет, в Tk нет встроенной функции автоматического переноса меток. Однако это можно сделать, привязавшись к событию <Configure> метки и затем отрегулировав длину переноса. Эта привязка будет срабатывать каждый раз при изменении размера виджета метки.

Другой вариант, как вы предлагаете, - использовать текстовый виджет. При желании можно полностью перекрыть границу. Это всегда было моим выбором, когда мне нужен учебный текст, заключенный в слова.

person Bryan Oakley    schedule 25.10.2010
comment
Брайан: Я последовал вашему совету, чтобы рассмотреть виджет «Текст», и опубликовал рабочий прототип в отредактированной версии моего первоначального вопроса. Еще раз спасибо за вашу помощь (в этом конкретном посте и многих других постах, которые вы сделали в Stackoverflow). С уважением, Малкольм (извините за неправильное написание вашего имени в комментарии выше) - person Malcolm; 25.10.2010

Используйте Message виджет:

Виджет Сообщение — это вариант Ярлыка, предназначенный для отображения многострочных сообщений. Виджет сообщения может переносить текст и регулировать его ширину для сохранения заданного соотношения сторон.

person RousseauAlexandre    schedule 11.05.2016

Вот код:

entry = Label(self, text=text,
    anchor=NW, justify=LEFT,
    relief=RIDGE, bd=2)
def y(event, entry=entry):
  # FIXME: make this a global method, to prevent function object creation
  # for every label.
  pad = 0
  pad += int(str(entry['bd']))
  pad += int(str(entry['padx']))
  pad *= 2
  entry.configure(wraplength = event.width - pad)
entry.bind("<Configure>", y )
person t7ko    schedule 03.04.2012

Предлагаемый некоторыми людьми виджет tkinter.Message НЕ использует стиль TTK, а это означает, что он будет выглядеть как мусор в интерфейсе TTK (тематическом).

Вы можете вручную применить цвета фона и переднего плана из темы TTK к tkinter.Message (создав экземпляр ttk.Style() и запросив цвета переднего и заднего плана TLabel активных тем из этого объекта стиля), но это того не стоит... потому что древний виджет Message имеет НУЛЕВЫЕ преимущества перед обычным ttk.Label ТТК.

Виджет tkinter.Message имеет свойство «соотношение сторон», которое определяет количество пикселей до его переноса.

Вместо этого ttk.Label имеет свойство wraplength=, которое определяет, сколько пикселей до переноса слов. Вы также должны использовать его свойства anchor= и justify=, чтобы настроить его в соответствии с вашими желаниями. С помощью этих свойств вы можете заставить свою метку вести себя так же, как старый виджет Message.

Пример: ttk.Label(root, text="foo", wraplength=220, anchor=tkinter.NW, justify=tkinter.LEFT). Создает красиво оформленную метку, которая навсегда оборачивает текст после 220 пикселей в ширину.

Что касается автоматического обновления длины обертки? Ну, вы должны прикрепиться к событию <Configure>, как говорили люди... Однако, если у вас есть полностью гибкое окно (которое изменяет свой размер, чтобы соответствовать всему содержимому) или сетка/фрейм, который является плавным и содержит метку, то вы не может автоматически вычислить его таким образом, потому что само родительское ОКНО/КОНТЕЙНЕР будет РАСШИРЯТЬСЯ всякий раз, когда метка становится слишком широкой. Это означает, что размер метки всегда будет изменяться до максимальной ширины, необходимой для размещения всего текста. Таким образом, автоматическое обновление длины обертки возможно только в том случае, если у самой метки есть некоторые ограничения на ее ширину (либо из-за того, что ее родительский контейнер имеет фиксированный размер/максимальный размер, либо сам по себе имеет фиксированный размер/максимальный размер). В этом случае, конечно, вы можете использовать configure для расчета новых номеров переноса, чтобы убедиться, что текст всегда переносится... Однако пример кода от t7ko сломан и больше недействителен, просто к вашему сведению.

person Mitch McMabers    schedule 14.10.2019