В данной статье мы рассмотрим, как получить выбранные ячейки из объекта сетки wxPython. В большинстве случае, получить секцию довольно просто, но, когда пользователь выделяет больше, чем одну ячейку, получение отобранных данных немного усложняется. Нам нужно будет создать пример кода, чтобы увидеть, как всё это выглядит. Давайте начнём!
Выбор ячеек сетки
В интернете есть интересная статья, посвящённая данной теме. Вы можете прочесть её здесь: http://ginstrom.com/scribbles/2008/09/07/getting-the-selected-cells-from-a-wxpython-grid/ (или вот вариант покороче http://bit.ly/2eqafsB). Как бы то ни было, в ней встречается несколько проблем, которые мы и будем рассматривать. Вот, взгляните на код:
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 91 92 93 94 95 96 97 98 99 100 101 |
import wx import wx.grid as gridlib class MyPanel(wx.Panel): """""" def __init__(self, parent): """Constructor""" wx.Panel.__init__(self, parent) self.currentlySelectedCell = (0, 0) self.myGrid = gridlib.Grid(self) self.myGrid.CreateGrid(12, 8) self.myGrid.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onSingleSelect) self.myGrid.Bind(gridlib.EVT_GRID_RANGE_SELECT, self.onDragSelection) selectBtn = wx.Button(self, label="Get Selected Cells") selectBtn.Bind(wx.EVT_BUTTON, self.onGetSelection) sizer = wx.BoxSizer(wx.VERTICAL) sizer.Add(self.myGrid, 1, wx.EXPAND) sizer.Add(selectBtn, 0, wx.ALL|wx.CENTER, 5) self.SetSizer(sizer) def onDragSelection(self, event): """ Получаем клетки, которые были выбраны посредством зажатия левой кнопки мыши и выделения """ if self.myGrid.GetSelectionBlockTopLeft(): top_left = self.myGrid.GetSelectionBlockTopLeft()[0] bottom_right = self.myGrid.GetSelectionBlockBottomRight()[0] self.printSelectedCells(top_left, bottom_right) def onGetSelection(self, event): """ Получаем клетки, которые выбраны в данный момент """ cells = self.myGrid.GetSelectedCells() if not cells: if self.myGrid.GetSelectionBlockTopLeft(): top_left = self.myGrid.GetSelectionBlockTopLeft()[0] bottom_right = self.myGrid.GetSelectionBlockBottomRight()[0] self.printSelectedCells(top_left, bottom_right) else: print(self.currentlySelectedCell) else: print(cells) def onSingleSelect(self, event): """ Получаем выделение одной ячейки посредством клика по ней или перемещения между клетками посредством клавиш-стрелок """ print("You selected Row %s, Col %s" % (event.GetRow(), event.GetCol())) self.currentlySelectedCell = (event.GetRow(), event.GetCol()) event.Skip() def printSelectedCells(self, top_left, bottom_right): """ Основано на коде из: http://ginstrom.com/scribbles/2008/09/07/getting-the-selected-cells-from-a-wxpython-grid/ """ cells = [] rows_start = top_left[0] rows_end = bottom_right[0] cols_start = top_left[1] cols_end = bottom_right[1] rows = range(rows_start, rows_end+1) cols = range(cols_start, cols_end+1) cells.extend([(row, col) for row in rows for col in cols]) print("You selected the following cells: ", cells) for cell in cells: row, col = cell print(self.myGrid.GetCellValue(row, col)) class MyFrame(wx.Frame): """""" def __init__(self): """Constructor""" wx.Frame.__init__(self, parent=None, title="Single Cell Selection") panel = MyPanel(self) self.Show() if __name__ == "__main__": app = wx.App(False) frame = MyFrame() app.MainLoop() |
А теперь давайте разбираться со всем этим. В первую очередь, мы создаём объект сетки, который мы называем self.myGrid. Мы биндим два узконаправленных события: EVT_GRID_SELECT_CELL и EVT_GRID_RANGE_SELECT. Это сделано лишь с целью демонстрации, ведь обычно вам не нужно биндить EVT_GRID_SELECT_CELL. Для события выделения одной ячейки мы вызываем хэндлер onSingleSelect.
Есть вопросы по Python?
На нашем форуме вы можете задать любой вопрос и получить ответ от всего нашего сообщества!
Паблик VK
Одно из самых больших сообществ по Python в социальной сети ВК. Видео уроки и книги для вас!
В нём мы используем объект события, чтобы захватить правильные столбик и ряд. Если вы просматривали статью, ссылку на которую я давал выше, вы заметили, что они использовали GetGridCursorRow и GetGridCursorCol. Я обнаружил, что они лишь возвращают клетки, уже были выбраны ранее, а не ту, которая выбрана в данный момент. Именно по этой причине мы используем метод объекта события вместо предложенного.
Также учтите, что мы обновляем значение self.currentlySelectedCell до равному тому, что соответствует выбранной в данный момент ячейке.
Другое событие сетки привязано к onDragSelection. В данном хэндлере события мы вызываем метод сетки под названием GetSelectionBlockTopLeft() и проверяем, чтобы убедиться в том, что он что-то возвращает. Если не возвращает – то мы ничего больше и не делаем.
Но если он всё-таки что-то вернул, то мы захватываем его содержимое и содержимое, возвращённое из GetSelectionBlockBottomRight(). Затем мы пропускаем всё это в наш метод printSelectedCells(). Данный код основан на описанном в статье, на которую я ссылался, хотя он был немного упрощён, так как я обнаружил, что оригинальный цикл приводит к ошибке. Проще говоря, данный метод создаёт два списка значений, используя функцию расстояния wxPython. Затем он расширяет список, используя понимание закреплённого списка. Наконец, он печатает все выбранные нами ячейки в stdout.
Учтите, что метод theprintSelectedCells не работает корректно в wxPython Phoenix.
Последний метод, достойный вашего внимания, это хэндлер события кнопки: onGetSelection. Данный метод вызывает метод сетки под названием GetSelectedCells(). Это вернёт клетки, которые были выделены кликами. Он также подойдёт, если пользователь выделил несколько клеток сразу. Если пользователь выбрал лишь одну клетку, тогда мы напечатаем self.currentlySelectedCell, так как он всегда идентичен значению текущего выбора.
Итоги
Как вы видите, получение выбранной ячейки или ячеек из объекта сетки может быть весьма заковыристым. Но, немного поработав, мы можем с этим справиться. Надеюсь, вам это пригодиться в текущих или будущих проектах.
Являюсь администратором нескольких порталов по обучению языков программирования Python, Golang и Kotlin. В составе небольшой команды единомышленников, мы занимаемся популяризацией языков программирования на русскоязычную аудиторию. Большая часть статей была адаптирована нами на русский язык и распространяется бесплатно.
E-mail: vasile.buldumac@ati.utm.md
Образование
Universitatea Tehnică a Moldovei (utm.md)
- 2014 — 2018 Технический Университет Молдовы, ИТ-Инженер. Тема дипломной работы «Автоматизация покупки и продажи криптовалюты используя технический анализ»
- 2018 — 2020 Технический Университет Молдовы, Магистр, Магистерская диссертация «Идентификация человека в киберпространстве по фотографии лица»