wxPython in Action. Глава 13. Создание списков (list control) и управление им (Перевод)
В этой главе мы поговорим о:
создании списков в различных стилях
работа с элементами в списке
реакции на выбор пользователем элемента из списка
редактирование меток и сортировка списка
создание большого списка (large list)
У всех нас есть списки, которые мы хотим просмотреть, и программисты на wxPython не исключение. В wxPython есть два управляющих элемента, которые Вы можете использовать для отображения информации при помощи списков. Самый простой — list box — обычный список из одной колонки, который можно прокручивать, похожий на то, что Вы можете получить в HTML при помощи
Эта глава будет говорить о более сложном способе отображения информации в форме списка — элементе управления list (list control), полноценном виджете списка. Он отображает ListCtrl с несколькими колонками информации для каждой строки, который можно отсортировать по каждой колонке и стиль отображения которого можно настроить. У Вас есть достаточно гибкости в настройке каждой части этого элемента.
13.1 Создание элемента управления list
List может быть создан в одной из 4-х форм:
иконка (плитка)
маленькая иконка (значки)
список
отчёт
Суть этого должна быть понятна всем, кто использует Проводник в Windows или Mac Finder — это соответствует способам отображения элементов в проводнике. Мы начнём наше исследование этого элемента с того, что посмотрим как его создать в каждой из этих форм.
13.1.1 Что такое режим «иконка»
List выглядит как панель отображения дерева файловой системы в MS Windows Explorer. Этот элемент управления отображает информацию в одном из четырёх режимов. По умолчанию используется режим иконка, где каждый элемент списка представлен иконкой с текстом под ней. Рисунок 13.1 показывает простой пример этого режима. Код для отображения этого примера приведён в листинге 13.1. Обратите внимание, что этот код зависит от некоторых .png файлов, которые расположены в той же папке, что и наш модуль. Эти файлы можно получить с сайта этой книги.
В листинге 13.1 демонстрационный фрейм создаёт список изображений (image list), который содержит ссылки на изображения, которые мы будем отображать; затем мы создаём и заполняем элемент list. Список изображения мы обсудим позже в этой главе.
13.1.2 Что такое режим «маленькая иконка»
Режим «маленькая иконка» (small icon) похож на режим «иконка», только использует маленькие значки. Рисунок 13.2 приводит пример того же самого списка в режиме «маленькой иконки».
Этот режим особенно полезен когда Вы хотите уместить в виджете много элементов, особенно если сами иконки не настолько детализированы, чтобы показывать их в исходном размере.
Рисунок 13.2 Простой list в режиме «маленькая иконка»
13.1.3 Что такое режим списка (list mode)?
В режиме списка элементы отображаются в нескольких колонках, автоматически заполняя каждую из них по очереди, как показано на рисунке 13.3
Этот режим имеет те же достоинства, что и режим «маленькая иконка»; выбор между ними (т.е. между расположением в строчку или в столбик) зависит от ваших предпочтений.
Рисунок 13.3 Простой list в режиме «список»
13.1.4 Что такое режим отчёта (report mode)?
В режиме отчёта list отображается в формате нескольких колонок, где каждый строк может иметь любое число столбцов, связанных с ним, как показано на рисунке 13.4
Рисунок 13.4 Простой list в режиме «отчёт»
Этот режим настолько отличается от режима «иконка», что стоит привести код, который нужен для создания такого отображения:
Листинг 13.2 Пример создания list'a в режиме «отчёт»
import wx import sys, glob, random import data class DemoFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, None, -1, «wx.ListCtrl in wx.LC_REPORT mode», size=(600,400)) il = wx.ImageList(16,16, True) for name in glob.glob(«smicon??.png»): bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG) il_max = il.Add(bmp) # Создаём list self.list = wx.ListCtrl(self, -1, style=wx.LC_REPORT) self.list.AssignImageList(il, wx.IMAGE_LIST_SMALL) # Добавляем колонки for col, text in enumerate(data.columns): self.list.InsertColumn(col, text) # Добавляем строки for item in data.rows: index = self.list.InsertStringItem(sys.maxint, item[0]) for col, text in enumerate(item[1:]): self.list.SetStringItem(index, col+1, text) # даём каждому элементу случайное изображение img = random.randint(0, il_max) self.list.SetItemImage(index, img, img) # Настраиваем ширину колонок self.list.SetColumnWidth(0, 120) self.list.SetColumnWidth(1, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(2, wx.LIST_AUTOSIZE) self.list.SetColumnWidth(3, wx.LIST_AUTOSIZE_USEHEADER) app = wx.PySimpleApp() frame = DemoFrame() frame.Show() app.MainLoop()
В следующем разделе мы обсудим как поместить значение в соответствующем месте. Логика отображения этого режима должна быть не так уж и сложна. Лучше всего использовать этот режим в случае, когда список содержит одну-две дополнительные колонки данных. Если же ваш список сложнее, или содержит больше данных, то тогда лучше использовать grid control, описанный в 14 главе.
13.1.5 Как я могу создать list?
Элемент list в wxPython является экземпляром класса wx.ListCtrl. Его конструктор похож на конструкторы других виджетов:
Эти параметры содержат значения, которые мы уже видели в конструкторах других виджетов. parent — это родительский виджет, в котором будет расположен list; id — идентификатор wxPython, где -1 обозначает автоматически сгенерированное значение. Явно расположение задаётся параметрами pos и size. style задаёт режим и остальные опции отображения — об этом мы ещё поговорим в этой главе. validator используется для проверки ввода и о нём мы говорили в 9 главе. Параметр name используется достаточно редко.
Флаг style — это битовая маска, которая определяет некоторые возможности этого элемента управления. Первый набор значений — это режим отображения элемента. Режим по умолчанию — wx.LC_ICON. Таблица 13.1 содержит остальные доступные режимы.
Стиль
Описание
wx.LC_ICON
Режим «иконка»
wx.LC_LIST
Режим «список»
wx.LC_REPORT
Режим «отчёт»
wx.LC_SMALL_ICON
Режим «маленькая иконка»
В режимах «иконка» и «маленькая иконка» доступны ещё три флага, которые определяют расположение иконки относительно списка. Значение по умолчанию — wx.LC_ALIGN_TOP, которе выравнивает иконки по вершине списка. Для выравнивания по левой стороне используйте wx.LC_ALIGN_LEFT. Стиль LC.AUTOARRANGE заворачивает иконки по достижении ими нижнего или правого угла окна.
Таблица 13.2 содержит стили отображения для режима «отчёт»:
Стиль
Значение по умолчанию
wx.LC_HRULES
Рисуе
т линии между строками list'a
wx.LC_NO_HEADER
Не отображает заголовки колонок
wx.LC_VRULES
Рисует линии между колонками list'a
Флаги битовых масок могут быть скомбинированы при помощи операции или. Используйте wx.LC_REPORT | wx.LC_HRULES | wx.LC_VRULES для того чтобы получить вид, похожий на решётку. По умолчанию все элементы list позволяют осуществлять множественный выбор. Для того, чтобы это изменить используйте флаг wx.LC_SINGLE_SEL. В отличие от остальных виджетов, которые мы видели до сих пор, list имеет ещё несколько методов, которые позволяют Вам изменить его флаги стилей уже в процессе выполнения. Метод SetSingleStyle(style, add=True) позволяет Вам добавить или удалить один флаг стиля, в зависимости от параметра add. Вызов listCtrl.SetSingleStyle(LC_HRULES, True) добавит горизонтальную линейку, тогда как listCtrl.SetSingleStyle(LC_HRULES, False) удалит её. Вызов SetWindowStyleFlag(style) позволяет Вам переустановить весь стиль, задав новые флаги, например, SetWindowsStyleFlag(LC_REPORT | LC_NO_HEADER). Эти методы полезны для изменения list'a на лету.
13.2 Управление элементами в list'e
После того, как list создан, Вы можете добавлять информацию в него. В wxPython для этой цели используются разные способы, зависящие от того, что Вы хотите добавить — текстовую информацию или изображения, ассоциированные с элементами list'a. В следующих разделах мы покажем как добавлять текст и изображения в ваш list.
13.2.1 Что такое image list и как к нему добавлять изображения
Перед тем, как мы сможем говорить о том, как информация добавляется в list, мы должны сказать несколько слов о том, как list работает с изображениями. Все изображения, используемые в этом элементе, должны быть сперва добавлены в image list, который представляет из себя проиндексированный массив изображений, сохранённых в элементе list. Когда Вы связываете изображение с определённым элементом в list, то для ссылки на изображение используется его индекс. Этот механизм позволяет быть уверенным в том, что каждое изображение загружено только один раз, вне зависимости от того, как часто оно используется в list. Что, в свою очередь, помогает сэкономить память в случаях, когда изображения используются по нескольку раз. Кроме того, это обегчает связь между несколькими версиями одного и того же изображения, что может быть полезно для различных режимов. Более подробно создание изображений и bitmap в wxPython обсуждается в главе 12.
Создание image list
image list является экземпляром wx.ImageList и для его создания используется следующий конструктор: wx.ImageList(width, height, mask=True, initialCount=1) Параметры width и height задают в пикселях размер изображения, которое будет добавлено в list. Изображения больше, чем указанный размер добавить нельзя. Если параметр mask = True, nj изображение рисуется с его маской, если она у него есть. Параметр initialCount задаёт начальный внутренний размер list'a. Если Вы знаете, что list будет большой, то указание этого размера может сэкономить память и время позже.
Добавление и удаление изображений
Вы можете добавить изображение в list при помощи метода Add(bitmap, mask=wx.NullBitmap), где bitmap и mask оба являются экземплярами wx.Bitmap. Аргумент mask является монохромным битовым изображением, которое определяет прозрачные части изображения, если они должны быть. Если битовое изображение уже имеет свою маску, то его маска и будет использоваться по умолчанию. Если маски у изображения нет и у Вас нет монохромной карты прозрачности, но Вы хотите чтобы какой-то цвет в изображении служил маской, Вы можете использовать метод AddWithColourMask(bitmap, colour), где colour — цвет wxPython (или его имя), который будет использоваться в качестве маски. Если у Вас есть объект wx.Icon, который Вы хотите добавить в image list, то используйте метод AddIcon(icon). Все методы добавления возвращают индекс изображения в list'e, который Вы можете позже использовать.
Следующий отрывок кода показывает пример создания image list (похоже на листинг 13.1)
il = wx.ImageList(32, 32, True) for name in glob.glob(«icon??.png»): bmp = wx.Bitmap(name, wx.BITMAP_TYPE_PNG) il_max = il.Add(bmp)
image list должен быть привязан к list при помощи следующего метода:
Для того, чтобы удалить изображение из image list, воспользуйтесь методом Remove(index), где index — индекс изображения в списке. Этот метод изменяет индексы всех изображений после удалённого, что может создать проблему,