На этом шаге рассмотрим реализацию первой части перетаскивания - drag.
Реализация первой части перетаскивания начинается с перезаписи методов mousePressEvent() и mouseMoveEvent(). В первом из этих методов сохраняется позиция указателя мыши, в которой была нажата кнопка. Эта позиция пригодится в методе mouseMoveEvent() для определения момента старта операции перетаскивания.
Демонстрация метода перетаскивания текстовой информации из окна виджета в окно редактора показана на рис. 1.

Рис.1. Перетаскивание текста
Ниже представлено определение класса Drag:
class Drag : public QLabel {
Q_OBJECT
private:
//атрибут m_ptDragPos предназначен для сохранения положения курсора мыши
//в момент нажатия левой кнопки
QPoint m_ptDragPos;
void startDrag()
{
//Создается объект класса QMimeData, в который, вызовом метода setText(),
//передается перетаскиваемый текст
QMimeData* pMimeData = new QMimeData;
pMimeData->setText(text());
//Создается объект перетаскивания класса QDrag, в конструктор которого
//передается указатель на виджет, из которого осуществляется перетаскивание
QDrag* pDrag = new QDrag(this);
pDrag->setMimeData(pMimeData);
//Вызов метода setPixmap() устанавливает небольшое растровое изображение,
//перемещаемое вместе с указателем мыши при перетаскивании
pDrag->setPixmap(QPixmap(img1_xpm));
//Метод exec() запускает операцию перетаскивания.
//В этот метод можно также передавать значения, влияющие на внешний вид
//пиктограммы, находящейся рядом с курсором мыши и поясняющей смысл
//действия перетаскивания. Например, для копирования это значение Qt::CopyAction,
//для перемещения — Qt::MoveAction, для создания ссылки — Qt::LinkAction.
//По умолчанию это значение устанавливается равным Qt::MoveAction.
pDrag->exec(Qt::MoveAction);
}
protected:
virtual void mousePressEvent(QMouseEvent* pe)
{
//если была нажата левая кнопка мыши,
//то осуществляется инициализация атрибута m_ptDragPos
if (pe->button() == Qt::LeftButton) {
m_ptDragPos = pe->pos();
}
QWidget::mousePressEvent(pe);
}
//Метод mouseMoveEvent() нужен для распознавания начала перетаскивания.
//Нажатие левой кнопки мыши и последующее перемещение указателя не всегда
//говорит о желании пользователя перетащить объект.
//Чтобы быть уверенным, необходимо вычислить расстояние между
//текущей позицией и той позицией, в которой была нажата левая кнопка мыши.
//Если это расстояние превышает величину, возвращаемую статическим
//методом startDragDistance() (обычно 4 пиксела), то можно считать,
//что перемещение указателя мыши было неслучайным и пользователь
//действительно хочет перетащить выбранный объект.
virtual void mouseMoveEvent (QMouseEvent* pe)
{
if (pe->buttons() & Qt::LeftButton) {
int distance = (pe->pos() - m_ptDragPos).manhattanLength();
if (distance > QApplication::startDragDistance()) {
//вызывается метод startDrag()
startDrag();
}
}
QWidget::mouseMoveEvent(pe);
}
public:
Drag(QWidget* pwgt = 0) : QLabel("Текст для перетаскивания", pwgt)
{
}
};Файлы приложения можно взять здесь.
На следующем шаге рассмотрим реализацию drop.