您的位置:首页 > 编程语言 > Qt开发

Qt之拖放

2016-05-04 17:00 645 查看

Qt之 拖放(drag 和 drop)

拖放是应用程序内或者应用程序之间数据传递的一种方式。通常是提供数据的复制和移动。拖放主要包括拖动和放下。有些窗口可能只需要提供拖动功能,有些窗口可能只需要放下,有些窗口可能两者功能都需要具备。Qt的一些控件不需要进行任何设置,就具备拖放功能,比如QLineEdit、QTextEdit。
QLineEdit可以接受拖动过来的字符串,而QTextEdit可以接受拖动的字符串以及拖动文件的路径。所需要做的就是创建一个对象,然后显示,如下:
  QLineEdit lineEdit;
  lineEdit.show();
  QTextEdit textEdit;
  textEdit.show();

QLineEdit接受文字拖放,测试效果:



QTextEdit接受文件拖放,显示文件的路径,支持多个文件一起拖放,测试效果:



QWidget实现拖放,需要设置接受拖放,
setAcceptDrops(true);

并实现下面事件:
  void dragEnterEvent(QDragEnterEvent *event);
  void dragMoveEvent(QDragMoveEvent *event);
  void dropEvent(QDropEvent *event);
  void mousePressEvent(QMouseEvent *event);
  void mouseMoveEvent(QMouseEvent *event);

如果我们只需要QWidget接受放下,那么就不需要实现:
  void mousePressEvent(QMouseEvent *event);
  void mouseMoveEvent(QMouseEvent *event);
这两个事件主要是,当我们需要QWidget实现拖动时才需要的。
QApplication提供了两种方式来启动一个拖动操作:
  QApplication::startDragDistance():通过鼠标移动的距离来判断是否启动拖放,默认是10个像素点。但也可以通过static void setStartDragDistance(int l);来进行自定义开始拖放的距离。
  QApplication::startDragTime():通过鼠标点击的时长来判断是否启动拖放,默认是500ms。也可以通过static void setStartDragTime(int ms);来自定义按压时长。
为了实现拖放,我们需要在mousePressEvent内记录鼠标按下的坐标点或者时间点,然后在mouseMoveEvent判断鼠标移动的距离或者按压时间是否满足拖放要求,从而启动拖放。

执行拖放操作,我们需要创建一个QDrag对象,此对象包含QMimeData,这里保存着我们需要拖动的数据。
示例:
void QDragDrop::mousePressEvent(QMouseEvent *event)
{
__super::mousePressEvent(event);
mStartPoint = event->pos();//起点
}

void QDragDrop::mouseMoveEvent(QMouseEvent *event)
{
__super::mouseMoveEvent(event);
if ((event->pos() - mStartPoint).manhattanLength() > QApplication::startDragDistance())//判断是否执行拖动
{
QDrag *drag = new QDrag(this);
QMimeData *mimeData = new QMimeData;
QByteArray byteArray;//存储数据
QDataStream stream(&byteArray,QIODevice::WriteOnly);//流,写数据
stream << QImage("C:\\Users\\dlp\\Desktop\\2.png");//读取一个图片的数据
mimeData->setData("MyImage", byteArray);//设置数据
drag->setMimeData(mimeData);//设置数据
drag->exec(Qt::MoveAction);//执行拖动
delete drag;
}
}
上述示例,读取了一个图片的数据保存在QMimeData里面,作为要传递的数据。并且设置了自定义格式"MyImage"。
效果如下:



示例代码如下:
#ifndef QDRAGDROP_H
#define QDRAGDROP_H

#include <QtWidgets/QWidget>
#include <QMouseEvent>
#include <QHBoxLayout>

class QDragDrop : public QWidget
{
Q_OBJECT

public:
QDragDrop(QWidget *parent = 0);
~QDragDrop();

protected:
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);

private:
QPoint mStartPoint;
QHBoxLayout  *m_HBox;
};

#endif // QDRAGDROP_H
#include "qdragdrop.h"
#include <QApplication>
#include <QDrag>
#include <QMimeData>
#include <QLabel>

QDragDrop::QDragDrop(QWidget *parent)
: QWidget(parent)
{
mStartPoint = QPoint(0, 0);
m_HBox = new QHBoxLayout(this);
setAcceptDrops(true);
setWindowTitle("QWidget");
}

QDragDrop::~QDragDrop()
{

}

void QDragDrop::mousePressEvent(QMouseEvent *event) { __super::mousePressEvent(event); mStartPoint = event->pos();//起点 } void QDragDrop::mouseMoveEvent(QMouseEvent *event) { __super::mouseMoveEvent(event); if ((event->pos() - mStartPoint).manhattanLength() > QApplication::startDragDistance())//判断是否执行拖动 { QDrag *drag = new QDrag(this); QMimeData *mimeData = new QMimeData; QByteArray byteArray;//存储数据 QDataStream stream(&byteArray,QIODevice::WriteOnly);//流,写数据 stream << QImage("C:\\Users\\dlp\\Desktop\\2.png");//读取一个图片的数据 mimeData->setData("MyImage", byteArray);//设置数据 drag->setMimeData(mimeData);//设置数据 drag->exec(Qt::MoveAction);//执行拖动 delete drag; } }

void QDragDrop::dragEnterEvent(QDragEnterEvent *event)
{
__super::dragEnterEvent(event);
if (event->mimeData()->hasFormat("MyImage"))
event->acceptProposedAction();
}

void QDragDrop::dragMoveEvent(QDragMoveEvent *event)
{
__super::dragMoveEvent(event);
if (event->mimeData()->hasFormat("MyImage"))
event->acceptProposedAction();
}

void QDragDrop::dropEvent(QDropEvent *event)
{
__super::dropEvent(event);
if (event->mimeData()->hasFormat("MyImage"))
{
QByteArray byteArray = event->mimeData()->data("MyImage");//取数据
QDataStream stream(&byteArray, QIODevice::ReadOnly);//流,读数据
QImage image;
stream >> image;
QLabel *pLabel = new QLabel(this);
pLabel->setPixmap(QPixmap::fromImage(image));
m_HBox->addWidget(pLabel);
}
}

如果我们只需要接收放下,不需要拖动的话,那么就不需要上述示例中的两个鼠标事件。下面实现了一个拖动图片到窗口并使用QLabel显示出来的示例:
效果:



示例代码:
#ifndef QSHOWIMAGE_H
#define QSHOWIMAGE_H

#include <QWidget>
#include <QHBoxLayout>
#include <QDragEnterEvent>
#include <QMimeData>

class QShowImage : public QWidget
{
Q_OBJECT

public:
QShowImage(QWidget *parent = 0);
~QShowImage();

protected:
void dragEnterEvent(QDragEnterEvent *event);
void dropEvent(QDropEvent *event);

private:
QHBoxLayout *mLayout;
};

#endif // QSHOWIMAGE_H
#include "QShowImage.h"
#include <QLabel>
#include <QDebug>

QShowImage::QShowImage(QWidget *parent)
: QWidget(parent)
{
mLayout = new QHBoxLayout(this);
setAcceptDrops(true);
setWindowTitle("ShowImage");
}

QShowImage::~QShowImage()
{

}

void QShowImage::dragEnterEvent(QDragEnterEvent *event)
{
__super::dragEnterEvent(event);
if (event->mimeData()->hasUrls())
event->acceptProposedAction();
}

void QShowImage::dropEvent(QDropEvent *event)
{
__super::dropEvent(event);
if (event->mimeData()->hasUrls())
{
QList<QUrl> urls = event->mimeData()->urls();
for each (QUrl url in urls)
{
QLabel *pLabel = new QLabel(this);
QImage image(url.toString().mid(8));
pLabel->setPixmap(QPixmap::fromImage(image));
mLayout->addWidget(pLabel);
}
}
}

对于QListWidget来说,拖放并不像上面那样复杂,仅仅设置一下,就可以实现QListWidgetItem的拖动:
  setDragEnabled(true);



实现代码:
QListWidget qlistWidget;
QStringList strList = { "Item1", "Item2", "Item3", "Item4", "Item5" };
qlistWidget.addItems(strList);
qlistWidget.setViewMode(QListView::IconMode);
qlistWidget.setDragEnabled(true);
qlistWidget.show();
但是上述只是移动了位置,Item的具体索引并没有发生改变。而且如果我们需要实现其他拖放功能,并不能满足我们的需求。那么我们就需要重新实现拖放事件,来自定义我们自己需要实现的功能。我实现了如何拖动Item,然后再添加一个Item的功能,两个QListWidgetItem并没有什么关联,只是为了展示如何实现。
效果:



示例代码:
#ifndef LISTWIDGET_H
#define LISTWIDGET_H

#include <QListWidget>
#include <QMouseEvent>

class ListWidget : public QListWidget
{
Q_OBJECT

public:
ListWidget(QWidget *parent = 0);
~ListWidget();

void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
private:

};

#endif // LISTWIDGET_H
#include "ListWidget.h"
#include <QDrag>
#include <QMimeData>
#include <QLabel>

ListWidget::ListWidget(QWidget *parent)
: QListWidget(parent)
{
QStringList strList = { "Item1", "Item2", "Item3", "Item4", "Item5" };
addItems(strList);
setViewMode(QListView::IconMode);
setDragEnabled(true);
setWindowTitle("QListWidget");
}

ListWidget::~ListWidget()
{

}

void ListWidget::dragEnterEvent(QDragEnterEvent *event)
{
__super::dragEnterEvent(event);
ListWidget *pList = qobject_cast<ListWidget *>(event->source());//拖动的源对象
if (pList && pList == this)
{
event->setDropAction(Qt::DropAction::CopyAction);//设置拖动动作,影响鼠标光标
event->accept();
}
}

void ListWidget::dragMoveEvent(QDragMoveEvent *event)
{
__super::dragMoveEvent(event);
ListWidget *pList = qobject_cast<ListWidget *>(event->source());//拖动的源对象
if (pList && pList == this)
{
event->setDropAction(Qt::DropAction::CopyAction);//设置拖动动作,影响鼠标光标
event->accept();
}
}

void ListWidget::dropEvent(QDropEvent *event)
{
__super::dropEvent(event);
ListWidget *pList = qobject_cast<ListWidget *>(event->source());//拖动的源对象
if (pList && pList == this)
{
QListWidgetItem *pItem = new QListWidgetItem(this);//执行释放后,要做的事情
pItem->setText(QString("Item").append(QString::number(count())));
addItem(pItem);
}
}

交流QQ:1245178753
本文地址:http://blog.csdn.net/u011417605/article/details/51316037
源码下载:http://download.csdn.net/detail/u011417605/9509997
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: