拖放2:基本原理

一、 拖放基本原理
1、 拖放操作包括两个动作:拖动(drag)和放下(drop 或称为放置)。当被拖动时拖动的数据会
被存储为 MIME 类型(见第 6 章文件对话框)的对象, MIME 类型使用 QMimeData 类来描
述。 MIME 类型通常由剪贴板和拖放系统使用,以识别不同类型的数据。
2、 拖动点(drag site): 拖动的起始位置。
3、 放下点(drop site): 被拖动的对象放下的位置,若部件不能接受拖动的对象, Qt 会改变光
标的形状(一个禁用形状)来向用户进行说明。

4、拖放的启动和结束:
1)、启动拖放:拖放通过调用 QDrag::exec()函数而启动,该函数是一个阻塞函数(但不会
阻塞主事件循环),这意味着在拖放操作结束之前,不会返回该函数,调用 QDrag::exe()
函数后, Qt 拥有对拖动对象的所有权,并会在必要时将其删除。
2)、结束拖放:当用户放下拖动或取消拖动操作时结束拖放。


5、 拖放产生的过程及事件
1)、 启动拖放后,会使数据被拖动,这时需要按住鼠标按键才能拖动需要拖动的数据,松
开鼠标按键时意味着拖动结束。在这期间会产生如下事件
2)、默认情况下,部件不接受放下事件。使用 QWidget::setAcceptDrops()函数可设置部件
是否接受放下事件(即,拖放完成时发送的事件)。只有在部件接受放下事件的情形下,
才会产生以下事件(见下图)。

3)、 QDragEnterEvent:拖动进入事件。 当拖动操作进入部件时,该事件被发送到部件,
忽略该事件,将会导至后续的拖放事件不能被发送。 通常在该部件上光标会在外观上
显示为禁用的图形。
4)、 QDragMoveEvnet:拖动移动事件。 当拖动操作正在进行时,以及当具有焦点时按下
键盘的修饰键(比如 Ctrl)时, 发送该事件, 要使部件能接收到该事件,则该部件必须接
受 QDragEnterEvent 事件。
5)、 QDropEvent:放下事件。在完成拖放操作时发送该事件,即当用户在部件上放下一个
对象时,发送此事件。要使部件能接收到该事件,则该部件必须接受 QDragEnterEvent
事件,且不能忽略 QDragMoveEvnt 事件。
6)、 QLeaveEvent:当拖放操作离开部件时发送该事件,注意:要使部件能接收到该事件,
必须要使拖动先进入该部件(即产生 QDragEnterEvent 事件),然后再离开该部件,才会
产生 QLeaveEvent 事件。因很少使用该事件,因此本文不做重点介绍。
7)、注:必须接受是指必须重新实现该事件的处理函数并接受该事件,不能忽略是指在处
件事理函数中不明确调用 ignore()函数忽略该事件,这意味着可以不必重新实现该事件
的处理函数。
8)、以上事件产生的顺序为: QDragEnterEvent、 QDragMoveEvnet、 QDropEvent
事件传递规则图示,注: acceptProposedAction()也表示接受事件(和accept()事件等价),该函数见后文。
     
 

6、编写拖放程序的步骤
1)、在需要接受放下数据的部件上调用 QWidget::setAcceptDrops()函数以使该部件能接受
拖放事件。
2)、启动拖放: 通常在 mousePressEvent()或 mouseMoveEvent()函数中启动拖放,记住启动
拖放就是调用 QDrag 对象的 exec()函数,因此也可以在 keyPressEvent()等函数中启动
拖放(因很少这样做,所以本文不介绍这种情况下的拖放)。 在此步把需要拖动的数据
保存在 QMimeData 对象中。
3)、重新实现需要接受放下数据的部件的 dragEnterEvent()事件处理函数。
4)、根据需要重新实现 dragMoveEvent 或 dropEvent()函数
下面以实现代码为例进行讲解
示例:简单的拖放

运行结果及说明

二、 使用拖放打开文件
拖放文件的基本步骤:文件需要使用 QFile 类来打开,然后才能读取或存入其内容,因此对
拖放的文件进行处理,其实就是获取文件的地址,而地址是使用 URL 来表示的,因此首先
需要判断拖放的数据是否含有 URL,然后读取出 URL 中保存的文件的地址,再打开文件,
然后读取文件的内容,有关流和文件的内容本章暂时不用深入了解,明白以下示例代码的作
用即可。下面是具体的示例步骤。

示例:拖放文件

//m.h 文件的内容
#ifndef M_H
#define M_H
#include<QtWidgets>
class C:public QPushButton{
Q_OBJECT
public: 
	C(QString t="",QWidget *p=0):QPushButton(t,p){}
	void dragEnterEvent(QDragEnterEvent * e)
	{
		//若拖动的数据包含一个 URL 则接受该事件,否则忽略该事件!!
		if(e->mimeData()->hasUrls())
		{ 
			e->accept(); 
		} 
		else 
			e->ignore(); 
	}
	void dropEvent(QDropEvent * e)
	{
		const QMimeData *pm=e->mimeData();
		QList<QUrl> u=pm->urls(); //读取出 URL 的地址列表。
		QString pth=u.at(0).toLocalFile(); //将地址转换为 QString
		if(!pth.isEmpty())
		{ 
			//判断地址 pth 是否为空
			QFile file(pth); //创建文件 file
			if(!file.open(QIODevice::ReadOnly)); //以只读方式打开文件
			QTextStream in(&file); //创建流用于读取文件的内容。
			setText(in.readAll()); 
		} 
	} //读出文件的内容,并设置为该部件的文本
};

class B:public QWidget{ 
Q_OBJECT
public:
	B(QWidget *p=0):QWidget(p)
	{
		/*注:实际编程时只需把按钮替换为 QTexeEdit 之类的部件即可,此处为避免复杂性及明白其原理,使
		用简单的按钮就可以了。 */
		C *pb1=new C("AAA",this); 
		pb1->move(22,22); 
		pb1->setAcceptDrops(true); 
	}
};
#endif // M_H


//m.cpp 文件的内容
#include "m.h"
int main(int argc, char *argv[])
{ 
	QApplication app(argc,argv);
	B w; w.resize(444,355); w.show(); 
	return app.exec(); 
}

运行结果及说明

三、


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值