QT为准确地识别拖放行为,使用两个变量设置识别拖放和单击的界限:QApplication::startDragTime,该变量描述了用户按下鼠标多长时间才开始一个拖放操作,500MS;QApplication::startDragDistance,该变量描述了用户按下鼠标时移动多少个像素才开始拖动,默认是4个像素。
在窗口部件的mousePressEvent()中开始一个拖放操作,代码框架如下:
void MainWindow::mousePressEvent( QMouseEvent* event )
{
if( event->button() == Qt::LeftButton)
{
QDrag* drag = new QDrag(this);
QMimeData* mimeData = new QMimeData;
mimeData->setText( textEdit->toPlainText());
drag->setMimeData( mimeData );
drag->setPixmap( dragPixmap);
Qt::DropAction dropAction = drag->start();
.....
}
}
QMimeData对象来描述拖放的数据,QMimeData是MIME类型数据的一个容器类。剪贴板的数据描述同样也使用QMimeData。
为使窗口部件能够接受拖放操作,调用setAcceptDrops(true)允许窗口部件接受拖放操作,同时还要实现dragEnterEvent和dropEvent两个事件处理函数。
dragEnterEvent函数事件在拖放数据到达目标widget时产生,在函数中用户只处理感兴趣的拖放数据,如下代码实现只支持文本数据的拖放。
void Window::dragEnterEvent( QDragEnterEvent* event)
{
if( event->mimeData()->hasFormat("text/plain")
event->acceptProposedAction();
}
为了接收拖放数据,还必须实现目标控件的dragMoveEvent或dropEvent响应函数。dropEvent函数完成解释接收的拖放数据,并通知接收的应用做相应的处理。
为了实现拖放自定义的数据类型,可以自定义MIME类型。所有的数据放在QByteArray的字节数组内,然后使用自定义的数据类型,实现如下:
QByteArray itemData;
QDataStream dataStream(&itemData, QIODevice::WriteOnly);
dataStream<<pixmap<<event->pos();
QMimeData *mimeData = new QMimeData;
mimeData->setData("application/mymimedata", itemData );
在接收放下的数据时,则使用QByteArray取出数据,然后用QDataStream读出数据。
QByteArray itemData = event->mimeData()->data("application/mymimedata");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
Graphics View框架下的拖放操作
在Graphics View框架中,拖放操作和QWidget中的略有不同。场景、视图、图元都可以处理自己的拖放事件。QGraphicsView直接继承自QWidget,所以它具备QWidget的拖放功能。当视图收到拖放操作时,将拖放事件转换为Graphics View的QGraphicsSceneDragDropEvent事件,然后将事件传递给场景。场景对这些事件进行调度,将它发送给在鼠标位置的图元。
拖放操作通常在按下鼠标并移动的时候产生,因此可以在mousePressEvent和mouseMoveEvent函数中获得原始窗口部件的指针。如下例:
void MyItem::mousePressEvent(QGraphicsSceneMouseEvent* event)
{
QMimeData* data = new QMimeData;
data->setHtml("<h1>ItemData<h1>");
QDrag drag(event->widget());
drag.setMimeData(data);
drag.start();
}
使用剪贴板
使用QClipboard类可以存取窗口系统的剪贴板。QCipboard支持和QDrag类相同的数据类型。获取方法如下:
clipboard = QApplication::clipboard();
在QT中使用QMimeData类来表示剪贴板交换的数据。将一些常用的数据存入到剪贴板可以使用setText,setImage,setPixmap函数。这些函数同QMimeData类中的成员类似,不同的是QMimeData类成员可以指定数据存储的位置,如果指定了存储到QClipboard::Clipboard则数据存放在剪贴板。将QLineEdit中的数据复制到剪贴板可以使用:
clipboard->setText( lineEdit->text(), QClipboard::Clipboard );