拖放1:QMimeData类型(拖放数据)

一、MIME类型
MIME 消息能包含文本、图像、音频、视频以及其他应用程序专用的数据。具体类型见:MIME 参考手册 。

二、描述
1、QMimeData类是记录有关其MIME类型的信息的数据提供容器。

2、QMimeData用于描述可以存储在剪贴板中 并通过拖放机制传输的信息。QMimeData对象将它们所持有的数据与相应的MIME类型相关联,以确保信息可以在应用程序之间安全地传输,并在同一应用程序中进行复制。

3、QMimeData对象通常使用new创建,并提供给QDrag或QClipboard对象。这是为了使Qt能够管理它们使用的内存。

4、一个QMimeData对象可以同时使用几种不同的格式存储相同的数据。 format()函数按首选项顺序返回可用格式的列表。 data()函数返回与MIME类型关联的原始数据,setData()为MIME类型设置数据。

例:一个接受URL拖动的小部件的代码: 

void MyWidget::dragEnterEvent(QDragEnterEvent *event)
{
    //若拖动的数据包含一个 URL 则接受该事件。
    if (event->mimeData()->hasUrls())
        event->acceptProposedAction();
}
 
void MyWidget::dropEvent(QDropEvent *event)
{
    //若拖动的数据包含一个 URL 则接受该事件。
    if (event->mimeData()->hasUrls())
    {
        foreach (QUrl url, event->mimeData()->urls()) 
        {
              ...
        }
    }
 }


三、三种可将自定义数据存储在QMimeData对象中的方法
1、可以使用setData()将自定义数据作为QByteArray直接存储在QMimeData对象中。 例如:

  QByteArray csvData = ...;
 
  QMimeData *mimeData = new QMimeData;
  mimeData->setData("text/csv", csvData);
2、将QMimeData子类化,然后重新实现hasFormat(),formats()和retrieveData()。

3、如果拖放操作发生在单个应用程序中,则我们可以将QMimeData子类化,并在其中添加额外的数据,并在接收者的drop事件处理程序中使用qobject_cast()。 例如:

void MyWidget::dropEvent(QDropEvent *event)
{
    const MyMimeData *myData = qobject_cast<const MyMimeData *>(event->mimeData());
    if(myData) 
	{
       //直接访问myData的数据(不通过QMimeData的API)
    }
}


四、特定平台的MIME类型
在Windows系统,formats()还将使用x-qt-windows-mime子类型返回MIME数据中可用的自定义格式,以指示它们表示非标准格式的数据。 格式将采用以下形式:

application/x-qt-windows-mime;value="<custom type>"

例如:

application/x-qt-windows-mime;value="FileGroupDescriptor"

application/x-qt-windows-mime;value="FileContents"

每种格式的值声明描述了数据编码的方式。可以使用多个数据值。 可以通过添加索引值来访问它们: 

application/x-qt-windows-mime;value="FileContents";index=0

application/x-qt-windows-mime;value="FileContents";index=1

在Windows系统,MIME格式并不总是直接映射到剪贴板格式。Qt提供QWinMime来将剪贴板格式映射为开放标准的MIME格式。 同样,QMacPasteboardMime将MIME映射到Mac系统。

五、成员函数

0、与常见 MIME 类型相关的函数


1、QMimeData()

构造一个新的MIME数据对象,其中没有数据。

2、void clear()

删除对象中的所有MIME类型和数据条目。

3、QVariant colorData()

如果存储在对象中的数据表示一种颜色(MIME类型:application / x-color),则返回一种颜色;否则返回空的QVariant。要将QVariant转换为QColor,只需使用qvariant_cast()。 例:

  if (event->mimeData()->hasColor()) {
      QColor color = qvariant_cast<QColor>(event->mimeData()->colorData());
      ...
  }
4、QByteArray data(const QString &mimeType)

以参数指定的MIME类型描述的格式返回存储在对象中的数据。

5、QStringList formats()

返回对象支持的格式列表。 这是对象可以为其返回合适数据的MIME类型的列表。 列表中的格式按优先级顺序排列。对于最常见的数据类型,可以使用hasText()、hasHtml()、hasUrls()、hasImage()、hasColor()。

6、bool hasColor() const

是否可以返回颜色(application / x-color)类型。

7、[virtual] bool hasFormat(const QString &mimeType)

可以返回参数指定的MIME类型的数据。

8、bool hasHtml()

是否可以返回HTML(text / html)类型。

9、bool hasText()

是否可以返回文本(text / plain)类型。

10、bool hasUrls()

是否可以返回网址列表(text / uri-list)。

11、QString html()

如果存储在对象中的数据是HTML(text / html),则返回一个字符串。

12、QVariant imageData()

如果对象可以返回图像,则返回存储QImage的QVariant;否则,返回空的QVariant。要将QVariant转换为QImage,只需使用qvariant_cast()。 例如:

 if (event->mimeData()->hasImage()) {
     QImage image = qvariant_cast<QImage>(event->mimeData()->imageData());
     ...
 }
13、void removeFormat(const QString &mimeType)

删除对象中相应格式的数据条目。

14、QVariant retrieveData(const QString &mimeType, QVariant::Type type)

返回具有给定类型的QVariant,其中包含mimeType指定的MIME类型的数据。 如果对象不支持给定的MIME类型或变体类型,则返回空QVariant。通用data()获取器和便捷函数(text(),html(),urls(),imageData()和colorData())调用此函数。如果要使用自定义数据结构(而不是setData()提供的QByteArray)存储数据,则可以重新实现它。然后还需要重新实现hasFormat()和format()。

15、void setColorData(const QVariant &color)

将对象中的颜色数据设置为给定的颜色。颜色对应于MIME类型application / x-color。

16、void setData(const QString &mimeType, const QByteArray &data)

将与mimeType给出的MIME类型关联的数据设置为data
对于最常见的数据类型,可以调用更高级别的函数setText()、setHtml()、setUrls()、setImageData()、setColorData()。

如果要在项目视图的拖放操作中使用自定义数据类型,则必须:

1.使用Q_DECLARE_METATYPE()宏将其注册为Qt元类型;

2.为其实现流运算符;

3.然后必须使用qRegisterMetaTypeStreamOperators()函数注册流运算符

例,设置自定义数据类型为MIME类型:

struct customData
{
    customData() {}
    int one;
    bool two;
    QString three;
    operator QVariant() const
    {
        return QVariant::fromValue(*this);
    }
    friend QDataStream& operator<<(QDataStream& out, const customData& player);
    friend QDataStream& operator>>(QDataStream& in, customData& player);
    friend QDebug operator<<(QDebug dbg, const customData&);
};
//2.为其(customData)实现流运算符;
inline QDataStream& operator<<(QDataStream& out, const customData& player)
{
    out << player.one;
    out << player.two;
    out << player.three;
    return out;
}
inline QDataStream& operator>>(QDataStream& in, customData& player)
{
    in >> player.one;
    in >> player.two;
    in >> player.three;
    return in;
}
QDebug operator<<(QDebug dbg, const customData & c)
{
    dbg.nospace() << QStringLiteral("customData输出") << "{ one = " << c.one <<" two = "<< c.two << "three = " <<c.three <<"}";
    return dbg;
}

//1.使用Q_DECLARE_METATYPE()宏将其(customData)注册为Qt元类型;
Q_DECLARE_METATYPE(customData);
 
int main(int argc, char *argv[])
{   
    //注册类型
	//3.用qRegisterMetaTypeStreamOperators()函数将其(customData)注册流运算符
    qRegisterMetaTypeStreamOperators<customData>("customData");
 
    //设置自定义类型
    customData custData;
    custData.one = 100;
    custData.two = true;
    custData.three = "xxxx";
    QMimeData mimeData;
 
    QByteArray outBa;
    outBa.resize(sizeof(customData));
 
    QBuffer buffer(&outBa);
    buffer.open(QIODevice::WriteOnly);
    QDataStream out(&buffer);
    out << custData;
    buffer.close();
    //把与 "application/customDate" 描述的格式相关联的数据,设置为 outBa。
    mimeData.setData("application/customDate",outBa);
 
    //输出数据
    QByteArray inBa = mimeData.data("application/customDate");
    QBuffer buf(&inBa);
    buf.open(QIODevice::ReadOnly);
    QDataStream in(&buf);
    customData custData2;
    in>>custData2;
    qDebug()<< custData2;
}

例二:

示例:使用 setData()函数处理自定义 MIME 类型的数据
//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 mouseMoveEvent(QMouseEvent *e)
	{
		QDrag *dg=new QDrag(this); 
		QMimeData *md=new QMimeData;//把需要拖动的数据,保存在 QMimeData 对象中
		QIcon ic("F:/1i.png"); 
		QString s="ZZZ"; 
		
		QByteArray ba;
		//使用流把数据 ic 和 s 写入 ba 中(流暂时先不用深入了解)。以只写方式创建一个流
		QDataStream in(&ba, QIODevice::WriteOnly); 
        //把 ic 和 s 的写入 ba 中
		in<<ic<<s; 	
		//设置自定义的 MIME 类型数据:其中 XXX(名称任意)为自定义的 MIME 类型,ba 为存储该类型数据的对象。
		md->setData("XXX",ba); 

		dg->setMimeData(md);//设置拖动数据 
		dg->exec(); //启动拖放
	}
	void dragEnterEvent(QDragEnterEvent * e)
	{ 
		//acceptProposedAction()也表示接受事件,和accept()事件等价
		e->acceptProposedAction(); 
	}
	void dropEvent(QDropEvent * e)
	{
		const QMimeData *dg= e->mimeData();
		if(dg->hasFormat("XXX"))
		{ 
			//判断是否是有自定义 MIME 类型 XXX。
			//读取自定义 MIME 类型 XXX 的数据,并保存在 ba 中
			QByteArray ba = dg->data("XXX");
			
			//以下语句表示使用流,把ba中的数据读取出来
			QDataStream out(&ba, QIODevice::ReadOnly);
			QIcon ic; QString s; out>>ic>>s;
			
			//设置此部件的(Icon、文本)为拖动对象中的Icon/文本
			//设置该部件的图标为 ic,文本为 s。
			setIcon(ic); 
			setText(s);
		}
		e->accept();
	} 
};

class B: public QWidget{ 
Q_OBJECT
public:
	B(QWidget *p=0):QWidget(p)
	{
		C *pb1=new C("AAA",this); pb1->move(22,22); pb1->setIcon(QIcon("F:/1i.png"));
		C *pb2=new C("BBB",this); pb2->move(99,22);
		//在需要接受放下数据的部件上:调用 QWidget::setAcceptDrops()函数,以使该部件能接受拖放事件。
		pb2->setAcceptDrops(true); 
		pb1->setAcceptDrops(false);
	}
};
#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(); 
}

17、void setHtml(const QString &html)

将内容设置为用于表示数据的HTML(MIME类型text / html)。

18、void setImageData(const QVariant &image)

将对象中的数据设置为给定的图像。从QImage到QVariant的转换是隐式的。例:

    mimeData->setImageData(QImage("beautifulfjord.png"));
19、void setText(const QString &text)

将文本设置为用于表示数据的纯文本(MIME类型text/plain)。

20、void setUrls(const QList<QUrl> &urls)

将存储在MIME数据对象中的URL设置为参数指定的URL。(MIME类型的text / uri-list)。

21、QString text()

返回数据的纯文本(MIME类型text/plain)表示形式。

22、QList<QUrl> urls()

返回MIME数据对象中包含的URL列表。

                        
原文链接:https://blog.csdn.net/kenfan1647/article/details/116050820

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值