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

Пример применения WxPython для создания нодового интерфейса. Часть 4: Реализуем Drag&Drop

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

В этой части мы добавим поддерку Drag&Drop к нашему приложению и обучим его таким образом создавать новые ноды.

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

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

9. Добавляем поддержку Drag&Drop

Помощь Drag&Drop — штука пригодная и знаменитая, но здесь мы ее будем применять не вовсе по назначению. Мы таким образом будем создавать новые ноды. Работает это дело довольно легко. Требуется сделать объект класса «wx.TextDropTarget» и передать его в способ «SetDropTarget» класса «wx.Window» от которого наследуется наш канвас. Соответственно, в момент дропа будет вызван способ «wx.TextDropTarget.OnDropText», тот, что нам и нужно будет реализовать. Для теста, реализация этого класса будет выглядеть так:

class TextDropTarget(wx.TextDropTarget):
    def __init__(self):
        wx.TextDropTarget.__init__(self)

    def OnDropText(self, x, y, data):
        print x, y, data

Сейчас при бросании текста в окно, в консоле будет печататься сообщение с позицией и самим текстом. Как вы могли догататься, для принятия файлов, существует схожий класс «wx.FileDropTarget», тот, что работает аналогичным образом, ну либо класс «wx.PyDropTarget», тот, что может принимать все и каждая.

10. Создаем ноды с Drag&Drop

Легко печатать текст не дюже пригодно, следственно мы используем полученный текст, Дабы создавать ноды с ним. Но для начала нужно немножко изменить архитектуру и добавить фабрику нод (это сгодится на грядущее). На данный момент — это будет дюже простая фабрика:

class NodesFactory(object):
    def __init__(self):
        pass

    def CreateNodeFromDescription(self, nodeDescription):
        return SimpleTextBoxNode(text=nodeDescription)

которая легко создает экземплят «SimpleTextBoxNode», тот, что является слегда продвинутым преемником «SimpleBoxNode»:

class SimpleTextBoxNode(SimpleBoxNode):
    def __init__(self, **kwargs):
        super(SimpleTextBoxNode, self).__init__(**kwargs)
        self.text = kwargs.get("text", "No text")

    def Render(self, gc):
        super(SimpleTextBoxNode, self).Render(gc)

        gc.DrawText(self.text, self.position[0] 10, self.position[1] 10)

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

    def CreateNodeFromDescriptionAtPosition(self, nodeDescription, pos):
        node = self._nodesFactory.CreateNodeFromDescription(nodeDescription)
        if node:
            node.position = pos
            self._canvasObjects.append(node)
            self.Render()

И немножко модернизировать TextDropTarget, Дабы он вызывал данный способ при поступлении текста:

class TextDropTarget(wx.TextDropTarget):
    def __init__(self, canvas):
        wx.TextDropTarget.__init__(self)
        self._canvas = canvas

    def OnDropText(self, x, y, data):
        print x, y, data
        self._canvas.CreateNodeFromDescriptionAtPosition(data, [x, y])

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

Код, как и неизменно, дозволено обнаружить в соответствующем коммите на GitHub’е.

11. Клонируем ноды с Drag&Drop

Но помимо создания нод, с поддержкой Drag&Drop дозволено также организовать и копирование нод, причем дюже легко. Если пользователь в момент начала перетаскивания ноды зажмет Ctrl, нам нужно легко инициировать предисловие Drag&Drop’а и отдать изложение ноды. А код создания ноды сделает для нас всю оставшуюся работу. Для инициации Drag&Drop’а мы добавим дальнейший код в обработчик нажатия левой кнопки мыши:

        if evt.ControlDown() and self._objectUnderCursor.clonable:
            text = self._objectUnderCursor.GetCloningNodeDescription()
            data = wx.TextDataObject(text)
            dropSource = wx.DropSource(self)
            dropSource.SetData(data)
            dropSource.DoDragDrop(wx.Drag_AllowMove)

Здесь мы создаем источник Drag&Drop’а и отдаем ему изложение, которое мы получили от ноды. Осталось реализовать способ «GetCloningNodeDescription» у ноды и все будет готово. Но вначале реализуем интерфейс:

class ClonableObject(CanvasObject):
    def __init__(self, **kwargs):
        super(ClonableObject, self).__init__(**kwargs)
        self.clonable = True

    def GetCloningNodeDescription(self):
        """
        GetNodeDescription should return a dictionary that contains 
        all information required for cloning this node at another position
        """
        raise NotImplementedError()

А сейчас теснее реализацию способа у ноды:

    def GetCloningNodeDescription(self):
        return self.text

которая легко отдает ее текст.
Нынешняя версия кода живет здесь.

12. Масштабирубщиеся ноды

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

    def Render(self, gc):
        textDimensions = gc.GetTextExtent(self.text)
        self.boundingBoxDimensions = [textDimensions[0] 20, textDimensions[1] 20] 
        super(SimpleTextBoxNode, self).Render(gc)

        gc.DrawText(self.text, self.position[0] 10, self.position[1] 10)

Способ «GetTextExtent» в данном случае возвращает размер прямоугольника, тот, что занимает текст. Соответственно перед рендерингом ноды, мы обновляем ее размеры так, Дабы она была на 10 пикселей огромнее текста с всякой стороны. Вот так сейчас выглядит каждый данный процесс:

Код живет в этом коммите на GitHub’е.

PS: Об опечатках пишите в личку.

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

Оставить комментарий
БАЗА ЗНАНИЙ
СЛУЧАЙНАЯ СТАТЬЯ
СЛУЧАЙНЫЙ БЛОГ
СЛУЧАЙНЫЙ МОД
СЛУЧАЙНЫЙ СКИН
НОВЫЕ МОДЫ
НОВЫЕ СКИНЫ
НАКОПЛЕННЫЙ ОПЫТ
Форум phpBB, русская поддержка форума phpBB
Рейтинг@Mail.ru 2008 - 2017 © BB3x.ru - русская поддержка форума phpBB