码迷,mamicode.com
首页 > 其他好文 > 详细

Qt之拖放

时间:2016-05-06 15:47:00      阅读:212      评论:0      收藏:0      [点我收藏+]

标签:

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

Qt之拖放

标签:

原文地址:http://blog.csdn.net/u011417605/article/details/51316037

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!