Статьи

wxPython: как получить выбранные ячейки в сетке

Сегодня мы рассмотрим, как получить выделенные ячейки из объекта сетки wxPython. В большинстве случаев получить раздел легко, но когда пользователь выбирает более одной ячейки, выбор становится более сложным. Нам нужно создать пример кода, чтобы показать, как все это сочетается. Давайте начнем!

Выбор ячейки сетки

В Интернете есть интересная статья, посвященная этой теме. Вы можете прочитать это здесь . Однако есть несколько проблем со статьей, которые мы также рассмотрим. Вот код, который мы рассмотрим:

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):
        """
        Gets the cells that are selected by holding the left
        mouse button down and dragging
        """
        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):
        """
        Get whatever cells are currently selected
        """
        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):
        """
        Get the selection of a single cell by clicking or 
        moving the selection with the arrow keys
        """
        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):
        """
        Based on code from 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 . В нем мы используем объект события, чтобы получить правильную строку и столбец. Если вы посмотрите на статью, на которую ссылается выше, вы заметите, что они используют GetGridCursorRow и GetGridCursorCol. Я обнаружил, что они возвращают только ранее выбранную ячейку, а не ячейку, которая выбрана в данный момент. По этой причине мы вместо этого используем методы объекта события. Также обратите внимание, что мы обновляем значениеself.currentlySelectedCell, чтобы равняться, какой бы ни была выбранная ячейка.

Другое событие сетки связано с onDragSelection . В этом обработчике события мы вызываем метод GetSelectionBlockTopLeft () сетки и проверяем, что он что-то возвращает. Если это не так, то мы больше ничего не делаем. Но если он что-то возвращает, то мы берем его содержимое, а также содержимое, возвращаемое из GetSelectionBlockBottomRight (). Затем мы передаем их в наш метод printSelectedCells . Этот код основан на ранее упомянутой статье, хотя он был немного упрощен, поскольку я обнаружил, что цикл for оригинала выдавал ошибку. По сути, все, что делает этот метод, — это создание двух списков значений с помощью функции диапазона Python. Затем он расширяет список, используя понимание вложенного списка. Наконец он распечатывает ячейки, которые были выбраны для stdout.

Последний метод, который нужно рассмотреть — это обработчик события кнопки: onGetSelection . Этот метод вызывает метод GetSelectedCells () сетки . Это вернет выбранные ячейки, которые были нажаты одним щелчком мыши. Это также будет работать, если пользователь перетаскивает выбранные ячейки. Если пользователь просто выберет одну ячейку, мы напечатаем self.currentlySelectedCell, так как он всегда будет равен значению текущего выделения.

Завершение

Как видите, получение выбранной ячейки или ячеек из объекта сетки может быть немного сложнее. Но с небольшим трудом мы смогли преодолеть. Надеюсь, вы найдете это полезным в одном из ваших текущих или будущих проектов.