[Предыдущая: Портирование на Qt 4 - Виртуальные функции] [Содержание] [Следующая: Портирование файлов UI в Qt 4]
Портирование на Qt 4 - Перетаскивание (Drag and Drop)
Qt 4 вводит новый набор классов для обработки операций перетаскивания для облегчения использования по сравнению с их аналогами в Qt 3. В результате, способ, которым выполняется перетаскивание, совершенно отличается от способа, ожидаемого разработчиками приложений Qt 3. В этом руководстве мы покажем отличия между старым и новым API и укажем, где нужно изменить приложения при портировании на Qt 4.
Перетаскивание
В Qt 3 операции перетаскивания инкапсулированы в QDragObject (смотрите Q3DragObject) и его подклассах. Эти объекты обычно создаются на куче в ответ на щелчок мыши или события перемещения мыши, и право собственности на них передаётся Qt, поэтому они могут быть удалены когда соответствующие операции перетаскивания завершены. Источник перетаскивания не контролирует как выполняется операция перетаскивания вызванной функцией drag() объекта, и не получает информации о том, как завершилась операция.
void MyQt3Widget::customStartDragFunction()
{
QDragObject *d = new QTextDrag( myHighlightedText(), this );
d->dragCopy();
// НЕ удаляйте d.
}
Аналогично, в Qt 4 операции перетаскивания также начинаются, когда создан объект QDrag и вызвана его функция exec(). По контрасту эти объекты являются обычно созданными не столько на куче сколько на стеке поскольку каждая операция перетаскивания выполняется синхронно, так как источник перетаскивания связан. Одно из ключевых преимуществ этого является то, что источник перетаскивания может получить из значения возвращённого exec() информацию о том, как завершилась операция.
void MyWidget::mousePressEvent(QMouseEvent *event)
{
if (event->button() == Qt::LeftButton) {
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
mimeData->setText(text);
mimeData->setImageData(image);
drag->setMimeData(mimeData);
drag->setPixmap(iconPixmap);
Qt::DropAction dropAction = drag->exec();
...
event->accept();
}
}
Ключевым отличием в вышеприведённом коде является использование класса QMimeData для сохранения информации о данных, которые переданы. Qt 3 основан на подклассах QDragObject для предоставления поддержки для конкретных MIME-типов; в Qt 4 использование QMimeData в качестве общего контейнера для данных делает взаимосвязь между MIME-типом и данными более прозрачной. QMimeData описывается более детально дальше в этом документе.
Отпускание
И в Qt 3, и в Qt 4 можно приготовить пользовательский виджет для приёма отпускаемых данных, включив свойство acceptDrops виджета, обычно, в конструкторе виджета. В результате, виджет получит события начала перетаскивания, которые могут быть обработаны его функцией dragEnterEvent(). Как и в Qt 3, пользовательские виджеты в Qt 4 обрабатывают эти события определяя, могут ли быть отпущены на виджете данные, поставляемые операцией перетаскивания. Так как классы, используемые для инкапсуляции MIME-данных, отличаются в Qt 3 и Qt 4, соответствующие реализации различны.
В Qt 3 событие начала перетаскивания обрабатывается проверкой, может ли каждый из стандартных подклассов QDragObject раскодировать поставленные данные, и указывает успех или неудачу этих проверок посредством функции accept() события, как показано в этом простом примере:
void MyQt3Widget::dragEnterEvent(QDragEnterEvent* event)
{
event->accept(
QTextDrag::canDecode(event) ||
QImageDrag::canDecode(event)
);
}
В Qt 4 вы можете изучить MIME-тип, описывающий данные, чтобы определить, будет ли виджет принимать событие или, для распространённых типов данных, вы можете использовать вспомогательные функции:
void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasText() || event->mimeData()->hasImage())
event->acceptProposedAction();
}
Виджет имеет некоторый контроль над типом выполняемой операции перетаскивания. В коде выше предлагаемое действие источника перетаскивания принято, но оно может быть перегружено если требуется.
И в Qt 3, и в Qt 4 необходимо принять данное событие перетаскивания для того, чтобы получить соответствующее событие отпускания. Пользовательский виджет в Qt 3, который может принимать отпускаемые данные в форме текста или изображений, должен предоставить реализацию dropEvent(), которая выглядит следующим образом:
void MyQt3Widget::dropEvent(QDropEvent* event)
{
QImage image;
QString text;
if ( QImageDrag::decode(event, image) ) {
insertImageAt(image, event->pos());
} else if ( QTextDrag::decode(event, text) ) {
insertTextAt(text, event->pos());
}
}
В Qt 4 событие обрабатывается аналогичным способом:
void MyWidget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasText())
dataLabel->setText(event->mimeData()->text());
else if (event->mimeData()->hasImage()) {
QVariant imageData = event->mimeData()->imageData();
dataLabel->setPixmap(qvariant_cast<QPixmap>(imageData));
}
event->acceptProposedAction();
}
Также можно извлечь данные, сохранённые для отдельного MIME-типа, если он был задан источником перетаскивания.
MIME-типы и данные
В Qt 3 передаваемые в операции перетаскивания данные инкапсулировались в экземплярах QDragObject и его подклассов, представляющих определённые форматы данных, связанных с общим MIME-типом и подтипами.
В Qt 4 только класс QMimeData используется для представления данных, предоставляя контейнер для данных, сохранённых в нескольких форматах, каждый связан с соответствующим MIME-типом. Так как могут быть заданы произвольные MIME-типы, нет необходимости в обширной иерархии классов для представления разных видов информации. Кроме того, QMimeData предоставляет несколько вспомогательных функций, чтобы разрешить наиболее распространённые форматов данных для сохранения и извлечения с меньшим усилием, чем для произвольных MIME-типов.
[Предыдущая: Портирование на Qt 4 - Виртуальные функции] [Содержание] [Следующая: Портирование файлов UI в Qt 4]
Авторские права © 2010 Nokia Corporation и/или её дочерние компании |
Торговые марки |
Qt 4.6.4 |
|