Позиция в строке

poziciya v stroke Экскурсия по tkinter, часть 2

Вторым ключом к пониманию виджета Text является определение позиции в строке текста. Как и виджеты списков, виджеты Text позволяют указывать эту позицию различными способами. Методы Text, ожидающие получить позицию, принимают индекс, метку или тег. Кроме того, некоторые особые операции вызываются с предопределенными метками или тегами — текстовый курсор вставки имеет метку INSERT, а текущее выделение имеет тег SEL. Так как они являются фундаментальными при работе с виджетом Text и обеспечивают большую часть его выразительности, рассмотрим поближе эти параметры настройки.

Индексы в Text. Будучи многострочным виджетом, Text поддерживает индексы строк и колонок. Например, рассмотрим интерфейсы базовых операций ввода, удаления и извлечения текста, используемые в этом сценарии:

self.text.insert(‘1.0’, text) # вставить текст в начало

self.text.delete(‘1.0’, END) # полностью удалить текущий текст

return self.text.get(‘1.0’, END+’-1c’) # получить текст от начала до конца

Во всех этих предложениях первый аргумент является абсолютным индексом, ссылающимся на начало строки с текстом: строка ‘1.0’ означает строку 1, колонку 0 (строки нумеруются с 1, а колонки с 0, однако аргумент ‘0.0’ также считается допустимым и интерпретируется как ссылка на начало текста). Индекс ‘2.1’ ссылается на второй символ во второй строке.

Как и в случае с виджетом списка, при работе с текстовым виджетом также можно использовать символические имена: END в предшествующем вызове метода delete указывает на позицию, находящуюся сразу за последним символом в строке текста (библиотека tkinter записывает в эту переменную end’). Аналогично символический индекс INSERT (на самом деле строка insert’) ссылается на позицию, находящуюся сразу за курсором вставки, место, где будут появляться символы, вводимые с клавиатуры. Символические имена, такие как INSERT, можно также назвать метками, которые будут описаны ниже.

Дополнительной точности можно достичь, добавляя к строкам индексов простые арифметические расширения. Индексное выражение END+’-1cв вызове метода get в предыдущем примере в действительности является строкой end-1cи ссылается на позицию за один символ до END. Поскольку END указывает на место сразу за последним символом строки текста, это выражение ссылается на сам последний символ. В результате расширение -1c отрезает замыкающий символ \n, который виджет добавляет к своему содержимому (и который может добавить пустую строку при сохранении в файле).

Аналогичные расширения строк индексов позволяют ссылаться на символы, находящиеся впереди (+1c), строки, находящиеся впереди и позади (+2l, -2l), а также на концы строк и начала слов, в которых находится индекс (lineend, wordstart). Индексы передаются большинству методов виджета Text.

Метки в Text. Помимо идентификаторов строка/колонка, позиции можно определять в виде имен меток — символических имен позиций между двумя символами. В отличие от абсолютных позиций строка/колонка, метки являются виртуальными адресами, которые перемещаются при вставке нового текста или его удалении (выполняемых сценарием или пользователем). Метка всегда ссылается на первоначальное местоположение, даже если оно смещается с течением времени в другую строку или колонку.

Для создания метки используется метод mark_set объекта Text, которому передается строка имени и индекс, определяющий ее логическое положение. Например, этот сценарий устанавливает текстовый курсор вставки в начало текста с помощью первого из вызовов:

self.text.mark_set(INSERT, ‘1.0’) # установить курсор вставки в начало

self.text.mark_set(‘linetwo’, ‘2.0’) # пометить текущую строку 2

Имя INSERT является специальной предопределенной меткой, идентифицирующей позицию текстового курсора вставки, — изменение ее влечет изменение позиции курсора вставки. Чтобы создать собственную метку, достаточно просто передать уникальное имя, как показано во втором вызове выше, и использовать его везде, где требуется указать позицию в тексте. Вызов метода mark_unset удаляет метку по имени.

Теги в Text. Кроме абсолютных индексов и символических имен меток виджет Text поддерживает понятие тегов — символических имен, ассоциируемых с одной или несколькими подстроками в текстовом содержимом виджета Text. Теги можно применять с разными целями, в том числе для представления позиции там, где это требуется: помеченные тегами элементы определяются индексами начала и конца, которые можно впоследствии передавать методам, требующим указания позиции.

Например, библиотека tkinter предоставляет встроенный тег с именем SEL — переменную с предопределенным строковым значением sel’, — которое автоматически ссылается на текст, выделенный в данный момент. Чтобы получить текст, выделенный (подсвеченный) с помощью мыши, вызовите любой из следующих методов:

text = self.text.get(SEL_FIRST, SEL_LAST) # теги для индексов от/до text = self.text.get(‘sel.first’, ‘sel.last’) # или строки и константы

Имена SEL_FIRST и SEL_LAST являются обычными переменными в модуле tkinter с предопределенными значениями, используемыми во втором вызове. Метод get ожидает получить два индекса. Чтобы получить текст по тегу, добавьте к его имени расширения .first и .last, которые дают индексы начала и конца.

Чтобы пометить тегом подстроку, можно вызвать метод tag_add виджета Text, передав ему строку с именем тега и позиции начала и конца (тегами можно помечать текст, добавляемый методом insert). Чтобы снять тег со всех символов в некоторой области текста, можно вызвать метод tag_remove:

self.text.tag_add(‘alltext’, ‘1.0’, END) # пометить тегом весь текст self.text.tag_add(SEL, index1, index2) # выделить от index1 до index2 self.text.tag_remove(SEL, ‘1.0’, END) # снять выделение со всего текста

Здесь в первой строке создается новый тег для всего текста в виджете — от начальной до конечной позиции. Во второй строке во встроенный тег выделения SEL добавляется диапазон символов — эти символы автоматически подсвечиваются, поскольку для этого тега предопределена такая настройка его элементов. В третьей строке все символы текста исключаются из тега SEL (снимаются все выделения). Обратите внимание, что метод tag_remove просто снимает тег с текста в указанном диапазоне — чтобы полностью удалить тег, нужно вызвать метод tag_delete. Кроме того, имейте в виду, что эти методы применяются к самим тегам — чтобы удалить фактический текст, следует использовать метод delete, представленный выше.

Можно также динамически отображать индексы в теги. Например, метод search возвращает индекс row.column первого вхождения строки между начальной и конечной позициями. Чтобы автоматически выделить найденный текст, его индекс следует добавить во встроенный тег SEL:

where = self.text.search(target, INSERT, END) # поиск от курсора вставки pastit = where + (‘+%dc% len(target)) # индекс за найденной строкой self.text.tag_add(SEL, where, pastit) # пометить и выделить найденную строку self.text.focus() # выбрать сам виджет Text

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

Подведем итоги: индексы, метки и позиции тегов можно использовать везде, где требуется указать позицию в тексте. Например, метод see прокручивает содержимое, пока требуемая позиция не окажется в области видимости, — он позволяет указывать позиции всеми тремя способами:

self.text.see(‘1.0’) # прокрутить вверх

self.text.see(INSERT) # прокрутить до метки курсора вставки

self.text.see(SEL_FIRST) # прокрутить до тега выделения

Теги также могут применяться для форматирования и привязки событий, но эти подробности будут обсуждаться в конце раздела.

Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011

Оцените статью
Секреты программирования
Добавить комментарий