Шаг 237.
Библиотека PyQt5.
Графическая сцена. Обработка событий. Обработка перетаскивания и сброса
На этом шаге мы рассмотрим алгоритм реализации сбрасывания и переноса, а также основные методы классов, участвующие с этом.
Прежде чем обрабатывать перетаскивание и сброс, необходимо сообщить системе, что графический объект может их обработать. Для этого следует вызвать метод
setAcceptDrops() класса QGraphicsItem и передать ему значение True.
Обработка перетаскивания и сброса в графическом объекте выполняется следующим образом:
- внутри метода dragEnterEvent() проверяется MIME-тип перетаскиваемых данных и действие. Если графический объект способен обработать сброс этих данных и соглашается с
предложенным действием, необходимо вызвать метод acceptProposedAction() объекта события. Если нужно изменить действие, методу setDropAction() объекта события передается
новое действие, а затем у того же объекта вызывается метод accept() вместо метода acceptProposedAction();
- если необходимо ограничить область сброса некоторым участком графического объекта, можно дополнительно определить в нем метод dragMoveEvent(). Этот метод будет постоянно
вызываться при перетаскивании внутри области графического объекта. При согласии со сбрасыванием следует вызвать у объекта события метод accept();
- внутри метода dropEvent() производится обработка сброса.
Обработать события, возникающие при перетаскивании и сбрасывании объектов, позволяют следующие методы:
- dragEnterEvent (self, <event>) - вызывается, когда перетаскиваемый объект входит в область графического объекта. Через параметр <event> доступен экземпляр класса QGraphicsSceneDragDropEvent;
- dragLeaveEvent (self, <event>) - вызывается, когда перетаскиваемый объект покидает область графического объекта. Через параметр <event> доступен экземпляр класса QGraphicsSceneDragDropEvent;
- dragMoveEvent (self, <event>) - вызывается при перетаскивании объекта внутри области графического объекта. Через параметр <event> доступен экземпляр класса QGraphicsSceneDragDropEvent;
- dropEvent (self, <event>) - вызывается при сбрасывании объекта в области графического объекта. Через параметр <event> доступен экземпляр класса QGraphicsSceneDragDropEvent.
Класс QGraphicsSceneDragDropEvent наследует все методы классов QGraphicsSceneEvent и QEvent и добавляет поддержку методов:
- mimeData () - возвращает экземпляр класса QMimeData с перемещаемыми данными и информацией о MIME-типе;
- pos () - возвращает экземпляр класса QPointF с координатами указателя мыши в пределах области объекта;
- scenePos () - возвращает экземпляр класса QPointF с координатами указателя мыши в пределах сцены;
- screenPos () - возвращает экземпляр класса QPoint с координатами указателя мыши в пределах экрана;
- possibleActions () - возвращает комбинацию возможных действий при сбрасывании;
- proposedAction () - возвращает действие по умолчанию при сбрасывании;
- acceptProposedAction () - подтверждает готовность принять перемещаемые данные и согласие с действием по умолчанию, возвращаемым методом proposedAction();
- setDropAction (<Действие>) - указывает другое действие при сбрасывании. После изменения действия следует вызвать метод accept(), а не acceptProposedAction();
- dropAction () - возвращает действие, которое должно быть выполнено при сбрасывании;
- buttons () - возвращает комбинацию обозначений всех кнопок мыши, нажатых в процессе перетаскивания;
- modifiers () - возвращает комбинацию обозначений всех клавиш-модификаторов (Shift, Ctrl, Alt и др.), что были нажаты в процессе перетаскивания;
- source () - возвращает ссылку на источник события или значение None.
В заключение рассмотрим небольшой пример (источник: http://python-3.ru/page/pyqt5-drag-drop): реализуем перетаскивание
текста из строки и поместим его на кнопку. В результате надпись на кнопке изменится.
Вот текст приложения:
import sys
from PyQt5.QtWidgets import QPushButton, QWidget, QLineEdit, QApplication
class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent)
self.setAcceptDrops(True)
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
def dropEvent(self, e):
self.setText(e.mimeData().text())
class Example(QWidget):
def __init__(self):
super().__init__()
self.initUI()
def initUI(self):
edit = QLineEdit('', self)
edit.setDragEnabled(True)
edit.move(30, 65)
button = Button("Button", self)
button.move(190, 65)
self.setWindowTitle('Пример drag & drop')
self.setGeometry(300, 300, 300, 150)
app = QApplication(sys.argv)
ex = Example()
ex.show()
app.exec_()
Архив с файлом можно взять
здесь.
Результат работы приложения:
Рис.1. Результат работы приложения
Прокомментируем приведенный текст программы.
Для того, чтобы перетащить текст на кнопку (виджет) QPushButton, мы должны переопределить несколько методов. Для этого создаём наш собственный класс
Button, который будет наследовать класс QPushButton:
class Button(QPushButton):
def __init__(self, title, parent):
super().__init__(title, parent)
self.setAcceptDrops(True)
. . . .
Делаем возможными события перетаскивания для виджета:
self.setAcceptDrops(True)
Сначала переопределяем метод dragEnterEvent(), сообщая о типе данных, который разрешаем перетаскивать. В нашем случае, это обычный текст:
def dragEnterEvent(self, e):
if e.mimeData().hasFormat('text/plain'):
e.accept()
else:
e.ignore()
Путём переопределения метода dropEvent(), определяем, что нужно делать после события перетаскивания. Здесь меняем надпись на кнопке:
def dropEvent(self, e):
self.setText(e.mimeData().text())
Виджет QLineEdit имеет встроенную поддержку операций перетаскивания. Все, что нужно сделать, - это вызвать метод setDragEnabled(), чтобы активировать её:
edit = QLineEdit('', self)
edit.setDragEnabled(True)
На следующем шаге мы рассмотрим фильтрацию событий.
Предыдущий шаг
Содержание
Следующий шаг