Виджеты списков достаточно просты в использовании, но в сравнении с виджетами, которые рассматривались до сих пор, они заполняются и обрабатываются довольно своеобразными способами. Многие методы виджета списка принимают индекс, указывающий на элемент списка. Нумерация элементов начинается с 0, но библиотека tkinter вместо целочисленных смещений принимает также особые строки имен: end — для ссылки на конец списка, active — для обозначения выбранной строки и другие. Поэтому обращение к виджету списка обычно можно оформить несколькими способами.
Например, следующий сценарий добавляет элементы к списку, находящемуся в окне, вызывая его метод insert и последовательно увеличивая смещение (начиная с нуля — эту операцию можно было бы автоматизировать с помощью встроенной функции enumerate):
list.insert(pos, label) pos = pos + 1
Но список можно также заполнить, добавляя элементы в конец, вообще не используя счетчик, — с помощью любой из следующих инструкций:
list.insert(‘end’, label) # добавление в конец: подсчет позиций не нужен list.insert(END, label) # END — константа со значением ‘end’ в tkinter
Виджет Listbox не имеет параметра, такого как command, с помощью которого обычно регистрируются обработчики событий нажатий кнопок, поэтому выделенные в нем элементы следует получать во время обработки событий других виджетов (например, щелчков на кнопках) либо обрабатывать сделанные пользователем выделения, внедряясь в протоколы других событий. Чтобы получить выбранное значение, в следующем сценарии выполняется привязка обработчика события <Double-1> двойного щелчка левой кнопкой мыши с помощью bind (рассмотренного ранее в этом обзоре).
В обработчике двойного щелчка этот сценарий получает выделенный в списке элемент с помощью следующей пары методов:
index = self.listbox.curselection() # получить индекс выделенного элемента label = self.listbox.get(index) # текст, соответствующий этому индексу
Эту операцию можно реализовать иначе. Обе следующие строки дают одинаковый результат: они получают содержимое строки с индексом ‘active’, то есть выбранной в данный момент:
label = self.listbox.get(‘active’) # получить по индексу active
label = self.listbox.get(ACTIVE) # в tkinter ACTIVE=’active’
Для иллюстрации, метод класса по умолчанию runCommand выводит выбранное значение при каждом двойном щелчке на элементе списка — сценарий получает его в виде строки с текстом выбранного элемента:
C:\…\PP4E\Gui\Tour> python scrolledlist.py
You selected: Lumberjack-2
You selected: Lumberjack-19
You selected: Lumberjack-4
You selected: Lumberjack-12
Виджеты списков могут служить отличными инструментами ввода данных даже без полос прокрутки. Они принимают также параметры настройки, определяющие цвет, шрифт и рельеф. Наряду с режимом выбора единственного элемента они также поддерживают возможность выбора нескольких элементов одновременно. По умолчанию используется режим выбора единственного элемента, но вы можете передать в аргументе selectmode четыре значения: SINGLE, BROWSE, MULTIPLE и EXTENDED (по умолчанию: BROWSE). Первые два из них определяют режимы выбора единственного элемента, а последние два позволяют выбирать сразу несколько элементов.
Эти режимы имеют очень тонкие отличия. Например, режим BROWSE напоминает SINGLE, но дополнительно позволяет перетаскивать выделенный элемент. Щелчок на элементе в режиме MULTIPLE изменяет его состояние, не оказывая влияния на состояние других элементов. Режим EXTENDED также позволяет выбирать несколько элементов, но использует порядок выделения, как принято в интерфейсе проводника файлов Windows — первый элемент выбирается простым щелчком, несколько элементов — щелчком, при удерживаемой клавише Ctrl, а диапазон элементов — щелчком, при удерживаемой клавише Shif t. Режим множественного выбора можно реализовать, как показано ниже:
listbox = Listbox(window, bg=’white’, font=(‘courier’, fontsz)) listbox.config(selectmode=EXTENDED)
listbox.bind(‘<Double-1>’, (lambda event: onDoubleClick()))
# onDoubeClick: извлекает сообщения, выбранные в списке selections = listbox.curselection() # кортеж строк чисел, 0..N-1
selections = [int(x)+1 for x in selections] # преобразует в int,
# переводит в диапазон 1..N
В режиме множественного выбора метод curselection возвращает список строк цифр, соответствующих позициям выбранных элементов, — если не выбран ни один элемент, возвращается пустой кортеж. В действительности этот метод всегда возвращает кортеж строк цифр, даже в режиме выбора единственного элемента (нам не пришлось беспокоиться об этом в примере 9.9, потому что метод get виджета при извлечении значения корректно воспринимает кортеж с одним элементом).
Вы можете самостоятельно поэкспериментировать с альтернативными режимами выбора, раскомментировав строку в примере 9.9, где определяется параметр selectmode, и изменяя значение. При этом двойной щелчок мышью в режиме множественного выбора может порождать сообщение об ошибке, потому что методу get будет передаваться кортеж более чем с одним индексом выбранного элемента (выведите его, чтобы убедиться в этом). Режим множественного выбора мы будем использовать в примере PyMailGUI, далее в этой книге (в главе 14), поэтому дальнейшее обсуждение этой темы я отложу до будущих примеров.
Использованная литература:
Марк Лутц — Программирование на Python, 4-е издание, I том, 2011