В небольшой серии статей будет описано использование 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)
который отображает выделение вокруг объекта, и вы можете увидеть этот результат, если щелкнете по одному из узлов:
Актуальный код, как всегда, можно найти в соответствующем зафиксировать на 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 #программирование
-
Преимущества Grafana Для Отдела Тестирования
19 Oct, 24 -
Crm-Система: Полный Алгоритм Внедрения
19 Oct, 24 -
Однопроектники
19 Oct, 24 -
Киберорганика. За И Против
19 Oct, 24