В небольшой серии статей будет описано использование WxPython для решения весьма специфической задачи по разработке пользовательского интерфейса, а также то, как сделать это решение универсальным.
Этот туториал предназначен для тех, кто уже начал изучать эту библиотеку и хочет увидеть что-то более сложное и целостное, чем самые простые примеры (хотя начнётся всё с относительно простых вещей).
В этой части мы добавим в наше приложение поддержку Drag&Drop и научим его создавать таким образом новые узлы.
Часть 1: Учимся рисовать Часть 2. Обработка событий мыши Часть 3. Продолжаем добавлять функции + обработку клавиатуры Часть 4. Реализация Drag&Drop Часть 5: Соединение узлов Кому интересно, добро пожаловать под кат.
9. Добавьте поддержку Drag&Drop.
Поддержка Drag&Drop — штука полезная и популярная, но здесь мы не будем использовать ее по прямому назначению.Вот как мы будем создавать новые узлы.
Работает эта штука довольно просто.
Нам нужно создать объект класса «wx.TextDropTarget» и передать его методу «SetDropTarget» класса «wx.Window», от которого унаследован наш холст. Соответственно, в момент дропа будет вызван метод «wx.TextDropTarget.OnDropText», который нам и нужно будет реализовать.
Для теста реализация этого класса будет выглядеть так:
Теперь когда вы кидаете текст в окно, в консоли будет печататься сообщение с позицией и сам текст. Как вы уже догадались, для приема файлов существует аналогичный класс «wx.FileDropTarget», который работает аналогичным образом, или класс «wx.PyDropTarget», который может принимать все и вся.class TextDropTarget(wx.TextDropTarget): def __init__(self): wx.TextDropTarget.__init__(self) def OnDropText(self, x, y, data): print x, y, data
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 и дать описание узла.
А код создания узла сделает за нас остальную работу.
Чтобы инициировать перетаскивание, мы добавим следующий код в обработчик щелчка левой кнопкой мыши: 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. Узлы масштабирования
Что ж, прежде чем завершить четвертую часть, давайте добавим еще одну оборочку.Давайте масштабируем узлы в соответствии с размером текста.
Для этого немного изменим метод отрисовки текстового узла: 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: Пожалуйста, пишите мне об опечатках.
Теги: #ui #framework #interface #wxpython #python #drag-and-drop #разработка веб-сайтов #python #программирование
-
Нетбуки — Лучший Способ Общения.
19 Oct, 24 -
Алкина
19 Oct, 24