Пример Использования Wxpython Для Создания Интерфейса Узла. Часть 3. Продолжаем Добавлять Функции + Обработку Клавиатуры

В небольшой серии статей будет описано использование WxPython для решения весьма специфической задачи по разработке пользовательского интерфейса, а также то, как сделать это решение универсальным.

Этот туториал предназначен для тех, кто уже начал изучать эту библиотеку и хочет увидеть что-то более сложное и целостное, чем самые простые примеры (хотя начнётся всё с относительно простых вещей).

В прошлой части мы реализовали обработку событий мыши, а теперь добавим еще одну функцию и реализуем обработку событий клавиатуры.

Часть 1: Учимся рисовать Часть 2. Обработка событий мыши Часть 3. Продолжаем добавлять функции + обработку клавиатуры Часть 4. Реализация Drag&Drop Часть 5: Соединение узлов Кому интересно, добро пожаловать под кат.



7. Выбор объектов

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

Правда, чтобы удалить, надо сначала указать, что мы хотим удалить, т.е.

выбрать объект, поэтому начнем не с удаления, а с выделения.

Для выбора все обычно используют одиночный клик, но насколько мне известно, в wxPython нет специального события одиночного клика, поэтому мы будем отслеживать его сами.

Сделаем это простейшим образом: если пользователь нажмет левую кнопку мыши и отпустит ее над тем же пикселем, то это щелчок.

Для этого нам нужно запомнить, где пользователь нажал кнопку (сохраним это в «self._lastLeftDownPos»), а при отпускании сравнить и сохранить выбранный объект:

  
  
  
  
  
  
   

def OnMouseLeftUp(self, evt): #Selection if (self._lastLeftDownPos and self._lastLeftDownPos[0] == evt.GetPosition()[0] and self._lastLeftDownPos[1] == evt.GetPosition()[1] and self._objectUnderCursor and self._objectUnderCursor.selectable): self._selectedObject = self._objectUnderCursor self.Render()

Ну а чтобы пользователь мог видеть, что он там выбрал, добавим в код рендеринга холста следующий фрагмент:

if self._selectedObject: gc.PushState() self._selectedObject.RenderSelection(gc) gc.PopState()

Все? Нет, не всё, внимательный читатель заметил, что мы проверили, выбираемый ли объект, и вызвали новый метод RenderSelection, который должен быть у всех выбираемых объектов.

Поэтому так же, как и при переезде, мы добавим новый базовый класс, от которого будут наследоваться все объекты, которые можно выделить:

class SelectableObject(CanvasObject): def __init__(self, **kwargs): super(SelectableObject, self).

__init__(**kwargs) self.selectable = True def RenderSelection(self, gc): """ RenderHighlighting method should draw an object with a selection border around it. """ raise NotImplementedError()

Кстати, поскольку наших базовых классов становится больше и все становится сложнее, теперь их конструкторы берут сколько угодно параметров и передают их вверх по иерархии наследования в виде словаря, о чем и говорит строчка «супер (SelectableObject, self).

__init__(*) в этом случае.

*кваргс)».

Остается только добавить в узел следующий код:

def RenderSelection(self, gc): gc.SetBrush(wx.Brush('#888888', wx.TRANSPARENT)) gc.SetPen(wx.Pen('#CC0000', 3, wx.DOT)) gc.DrawRectangle(self.position[0]-2, self.position[1]-2, self.boundingBoxDimensions[0]+4, self.boundingBoxDimensions[1]+4)

который отображает выделение вокруг объекта, и вы можете увидеть этот результат, если щелкнете по одному из узлов:

Пример использования WxPython для создания интерфейса узла.
</p><p>
 Часть 3. Продолжаем добавлять функции + обработку клавиатуры

Актуальный код, как всегда, можно найти в соответствующем зафиксировать на GitHub .



8. Удаление объектов

Теперь мы подошли к удалению объектов.

Чтобы удалить, нам нужно отслеживать, когда пользователь нажимает кнопку «Удалить», и фактически удалять элемент, если он удаляется.

Для начала нам понадобится обработчик событий нажатия кнопок клавиатуры, который мы зарегистрируем так:

self.Bind(wx.EVT_KEY_DOWN, self.OnKeyPress)

А сам обработчик выполнит следующий код:

def OnKeyPress(self, evt): if evt.GetKeyCode() == wx.WXK_DELETE: if self._selectedObject and self._selectedObject.deletable: self._selectedObject.Delete() if self._selectedObject in self._canvasObjects: self._canvasObjects.remove(self._selectedObject) self._selectedObject = None else: evt.Skip() #Update object under cursor pos = self.CalcUnscrolledPosition(evt.GetPosition()).

Get() self._objectUnderCursor = self.FindObjectUnderPoint(pos) self.Render()

Здесь в случае события о нажатии кнопки с кодом wx.WXK_DELETE мы проверяем, выбран ли объект и удаляется ли он.

Если он есть, мы уведомляем его о том, что ему пора уйти в отставку (вызвав метод «Delete») и удаляя его из списка объектов на холсте.

evt.Skip() сообщает системе вызвать другие обработчики этого события, зарегистрированные в других местах.

Теперь, как обычно, остаётся добавить базовый класс для удаляемых объектов:

class DeletableObject(CanvasObject): def __init__(self, **kwargs): super(DeletableObject, self).

__init__(**kwargs) self.deletable = True def Delete(self): """ Delete method is called when an object is deleted from a canvas. """ raise NotImplementedError()

И вы можете получать удовольствие от удаления объектов с холста.

Правда, не очень долго, так как добавление объектов будет только в следующей части :) Текущая версия кода находится в этот коммит на GitHub .

PS: Пожалуйста, пишите мне об опечатках.

Теги: #ui #framework #interface #wxpython #python #события клавиатуры #удаление объектов #WXK_DELETE #evt.Skip() #kwargs #python #программирование

Вместе с данным постом часто просматривают: