Главная
Блог разработчиков phpBB
 
+ 17 предустановленных модов
+ SEO-оптимизация форума
+ авторизация через соц. сети
+ защита от спама

Пример применения WxPython для создания нодового интерфейса. Часть 3: Продолжаем добавлять фичи обработка клавиатуры

Anna | 16.06.2014 | нет комментариев
В маленьком цикле статей будет описано применение WxPython для решения абсолютно определенной задачи по разработке пользовательского интерфейса, да еще и то, как сделать это решение универсальным. Туториал данный расчитан на тех, кто теснее начал постигать эту библиотеку и хочет увидеть что-то больше трудное и целостное, чем простейшие примеры (правда начнется все с касательно примитивных пророческой).

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

Часть 1: Учимся рисовать
Часть 2: Обработка событий мыши

Кому увлекательно, добросердечно пожаловать под кат…

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()

Все? Нет не все, внимательный читатель подметил, что мы проверяли, является ли объект selectable и вызывали новейший способ 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()

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

    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. Удаление объектов

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

        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: Об опечатках пишите в личку.

Источник: programmingmaster.ru

Оставить комментарий
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB