Не буду спорить wxPython ListCtrl – это очень удобный виджет, но иногда его бывает крайне неудобно использовать. Это утверждение побудило Филипа Пайпера, миссионера из Мозамбика, написать ObjectListView, враппер для wx.ListCtrl. Сейчас идея его использования активно поддерживается комьюнити пользователей wxPython.
ObjectListView действительно обладает расширенной функциональностью, потому, что он позволяет объектам создавать собственные строки и, таким образом, значительно упрощает получение информации из нескольких колонок. Мистер Пайпер также добавил множество других удобных фишек, делающих добавление обычных редакторов, настройку цвета строк, автоматическую сортировку строк, и многое-многое другое, гораздо проще.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
Данная статья научит вас азам использования ObjectListView, так что вы сможете использовать его возможности в ваших будущих проектах. Это не будет исчерпывающим разбором полной его функциональности, но вполне сойдёт за неплохо написанную инструкцию.
Стоит отметить, что ObjectListView не является заменой для стандартного контроля списков. Его настройка немного отличается. К счастью, вы можете установить ObjectListView используя pip.
1 |
pip install objectlistview |
Давайте взглянем на достаточно простой пример. Мы создадим простой класс, который ObjectListView будет использовать в качестве своей дата-модели.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
class Book(object): """ Модель объекта Книги Содержит следующие атрибуты: 'ISBN', 'Author', 'Manufacturer', 'Title' """ def __init__(self, title, author, isbn, mfg): self.isbn = isbn self.author = author self.mfg = mfg self.title = title |
Вы можете сохранить этот фрагмент в отдельный файл, или же сразу добавить в файл кода, который вы будете использовать по мере продвижения в этой статье. Всё, что этот класс делает, это определяет нашу дата-модель, которая будет совпадать с колонками в нашем виджете ObjectListView. Теперь мы переходим к коду wxPython:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 |
import wx from ObjectListView import ObjectListView, ColumnDefn class MainPanel(wx.Panel): def __init__(self, parent): wx.Panel.__init__(self, parent=parent, id=wx.ID_ANY) self.products = [Book("wxPython in Action", "Robin Dunn", "1932394621", "Manning"), Book("Hello World", "Warren and Carter Sande", "1933988495", "Manning") ] self.dataOlv = ObjectListView(self, wx.ID_ANY, style=wx.LC_REPORT|wx.SUNKEN_BORDER) self.setBooks() # Позволяет редактировать ячейки таблицы после двойного клика по ним self.dataOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK # Создаёт кнопку обновления updateBtn = wx.Button(self, wx.ID_ANY, "Update OLV") updateBtn.Bind(wx.EVT_BUTTON, self.updateControl) # Создаёт кое-какие сайзеры mainSizer = wx.BoxSizer(wx.VERTICAL) mainSizer.Add(self.dataOlv, 1, wx.ALL|wx.EXPAND, 5) mainSizer.Add(updateBtn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(mainSizer) def updateControl(self, event): """ Обновляет виджет просмотра объектов списка """ print "updating..." product_dict = [{"title":"Core Python Programming", "author":"Wesley Chun", "isbn":"0132269937", "mfg":"Prentice Hall"}, {"title":"Python Programming for the Absolute Beginner", "author":"Michael Dawson", "isbn":"1598631128", "mfg":"Course Technology"}, {"title":"Learning Python", "author":"Mark Lutz", "isbn":"0596513984", "mfg":"O'Reilly"} ] data = self.products + product_dict self.dataOlv.SetObjects(data) def setBooks(self, data=None): self.dataOlv.SetColumns([ ColumnDefn("Title", "left", 220, "title"), ColumnDefn("Author", "left", 200, "author"), ColumnDefn("ISBN", "right", 100, "isbn"), ColumnDefn("Mfg", "left", 180, "mfg") ]) self.dataOlv.SetObjects(self.products) class MainFrame(wx.Frame): def __init__(self): wx.Frame.__init__(self, parent=None, id=wx.ID_ANY, title="ObjectListView Demo", size=(800,600)) panel = MainPanel(self) class GenApp(wx.App): def __init__(self, redirect=False, filename=None): wx.App.__init__(self, redirect, filename) def OnInit(self): # Здесь создаётся рамка frame = MainFrame() frame.Show() return True def main(): """ Здесь создаётся рамка """ app = GenApp() app.MainLoop() if __name__ == "__main__": main() |
Когда вы запустите этот код, то увидите приложение, которое должно выглядеть вот так:
Теперь давайте разберёмся с тем, что этот код делает. Начнём с того, что я создаю общий класс Book, который имеет несколько свойств: isbn, автор, название и издательство. Мы будем использовать этот класс, чтобы создавать строки в ObjectListView.
Затем мы создаём стандартную панель и помещаем на неё ObjectListView и кнопочный виджет. Вы также заметите, что здесь есть короткий список объектов «Book». ObjectListView настроен на режим отчёта посредством флага стиля LC_REPORT. Также есть ещё два режима, но я не буду уделять им внимания в этой статье. Режим отчёта выглядит примерно также как режим деталей в Проводнике Windows.
Следующий фрагмент кода может вам показаться немного странным:
1 |
self.dataOlv.cellEditMode = ObjectListView.CELLEDIT_SINGLECLICK |
Этот код приказывает нашему виджету разрешить редактирование всех ячеек в строке посредством двойного клика по ним. Я не знаю, почему он выглядит именно так, и почему в нём прописано, что вам нужно сделать лишь один клик. Даже документация говорит о том, что одного клика будет достаточно. Наверное, это какое-то ограничение Windows. В любом случае, чтобы отредактировать первую ячейку любой строки, просто выберите её и нажмите F2.
Последние несколько строк метода инициализации посвящены помещению виджетов в сайзеры. Следующим интересным фрагментом кода является метод updateControl, который собственно обновляет контент нашего ObjectListView. Здесь я показываю два разных способа обновления.
Первый: использование продуктивного листа объектов «Book» и вызов метода SetObjects, со вставленным в него списком. Второй: использование словаря. Ключи словаря должны соответствовать именам valueGetter в ColumnDefn (имена valueGetter вы могли заметить в методе setBooks). Значения словаря могут быть любыми. В моём примере, я действительно комбинирую список объектов «Book» и список словарей, а затем вызываю SetObjects для результатов.
В методе setBooks мы определяем колонки ObjectListView. Это делается посредством прохода списка объектов ColumnDefn через метод ObjectListView, который называется SetColumns. ColumnDefn обладает массой параметров, но нас интересуют только первые четыре из них.
Первый аргумент – заголовок колонки, второй аргумент – выравнивание всей колонки как единого целого, третий аргумент – это ширина колонки, четвёртый аргумент – это имя valueGetter. Имя должно соответствовать ключам в словаре (если вы используете метод со словарями, описанный выше) или свойствам класса, который вы используете (в нашем случае это класс Book). В обратном случае, некоторые данные могут не отобразиться в виджете.
Если вы хотите узнать больше о доступе к некоторой информации из объекта строки, тогда добавьте в своё приложение кнопку, а затем забиндите к ней соответствующую функцию:
1 2 3 4 5 |
def getRowInfo(self, event): """""" rowObj = self.dataOlv.GetSelectedObject() print rowObj.author print rowObj.title |
Теперь вы можете выбрать строку и использовать метод ObjectListView, который называется GetSelectedObject, чтобы получить объект строки. Как только вы его получите – вам откроется доступ к свойствам объекта, таким как автор или заголовок, или что вы там у себя определяли. Таким образом всё получается гораздо проще, чем в ListCtrl, где нам нужно было получать колонку и строку, чтобы найти информацию о каждом итеме.
Итоги
Данная статья рассказывает об азах использования ObjectListView. Убедитесь в том, что вы загрузили исходник, так как в нём есть масса интересных и полезных демок, среди которых одна, позволяющая пользователям редактировать некоторые ячейки, используя комбо-бокс, нарисованный самим автором. Документация также тщательно проработана и неплохо систематизирована. Я всегда делаю выбор в пользу ObjectListView, так как им гораздо проще пользоваться, плюс, его функционал намного шире.
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»