一、简介
首先选择窗体显示风格,接着显现拖拽效果,文字和图标都可以作为拖拽的对象,在窗体中的文字图标可以拖拽到窗口的任意位置,它们在两个独立运行的程序间也可相互拖拽(此时是复制一份到拖拽目的程序窗口中),文字拖拽的范围更广(须注意字符集的转换)。本文解决这种比较神秘的效果,熟悉拖拽的基本流程。
二、运行图
(1)总体效果图如下图1所示。左边风格设置,中间文字区,右侧拖拽区。
![](https://img-blog.csdn.net/20140630213014562?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
(2)拖拽的实现过程,如下图2所示。
![](https://img-blog.csdn.net/20140630213910437?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
实现拖拽最基本的工作有3部分:一、在可拖拽对象的mousePressEvent()函数中构建QDrag对象,并调用start()函数等待DropAction的返回。二、在放置可拖拽对象的容器类中,实现dragEnterEvent()函数,判断并设置应采用何种DropAction,返回给start()函数。三、在放置可拖拽对象的容器类中,实现dragEnterEvent()函数,创建一个新的可拖拽对象并在当前鼠标位置进行显示,同时判断并设置应采用何种DropAction,返回给start()函数。
三、详解
1、窗体风格
(1)系统支持的7中窗体风格,如下图所示。
![](https://img-blog.csdn.net/20140630214949296?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215056546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215205078?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215331546?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215545562?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215618156?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
![](https://img-blog.csdn.net/20140630215655640?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- QLabel *label = new QLabel(QObject::tr("窗体风格:"));
- QComboBox *styleComboBox = new QComboBox;
- styleComboBox->addItems(QStyleFactory::keys());
- styleComboBox->setCurrentIndex(5);
-
- void DragWidget::slotChangeStyle(QString style)
- {
- QApplication::setStyle(QStyleFactory::create(style));
- QApplication::setPalette(QApplication::style()->standardPalette());
- }
QStyleFactory::keys()获得当前系统支持的窗体风格,QApplication的setStyle()函数设置为刚创建的风格,调用setPalette()完成窗体显示的改变。
2、拖拽文字
(1)同一实例程序拖拽(移动)
中间控件的文字都拖放到右侧,通过光标的选择分解它们。
![](https://img-blog.csdn.net/20140701112453071?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- void DragLabel::mousePressEvent(QMouseEvent * e)
- {
- QString str = text();
- QPixmap pix;
- pix = pix.grabWidget(this);
-
- QByteArray data;
- QDataStream stream(&data,QIODevice::WriteOnly);
- stream << str << QPoint(e->pos()-rect().topLeft());
- QMimeData *mimeData = new QMimeData;
- mimeData->setData("Drag-Text",data);
- mimeData->setText(str);
-
- QDrag *drag = new QDrag(this);
- drag->setMimeData(mimeData);
- drag->setHotSpot(QPoint(e->pos() - rect().topLeft()));
- drag->setPixmap(pix);
-
- hide();
-
- Qt::DropAction dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);
-
- if (dropAction == Qt::MoveAction)
- close();
- else
- show();
- }
(2)不同实例程序拖拽(复制)
左侧文字向右侧程序中拖拽。
![](https://img-blog.csdn.net/20140701112927444?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
(3)外部程序拖拽交互
文本间的来回移动,以空格为分隔标志,也可以复制一段文字,但暂时没法控制文字的长度显示。
![](https://img-blog.csdn.net/20140701113418057?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- void DragWidget::dropEvent(QDropEvent *e)
- {
- if (e->mimeData()->hasFormat("Drag-Icon")) {
- QByteArray data = e->mimeData()->data("Drag-Icon");
- QDataStream stream(&data,QIODevice::ReadOnly);
- QPixmap pix;
- QPoint offset;
- stream >> pix >> offset;
-
- DragIcon *icon = new DragIcon(pix,this);
- icon->move(e->pos() - offset);
- icon->resize(50, 50);
- icon->show();
- if (children().contains(e->source())) {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else e->acceptProposedAction();
- }
- else if (e->mimeData()->hasFormat("Drag-Text"))
- {
- QByteArray data = e->mimeData()->data("Drag-Text");
- QDataStream stream(&data,QIODevice::ReadOnly);
- QString text;
- QPoint offset;
- stream >> text >> offset;
-
- DragLabel *label = new DragLabel(text,this);
- label->move(e->pos() - offset);
- label->show();
-
- if (children().contains(e->source())) {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else e->acceptProposedAction();
- }
- else if (e->mimeData()->hasText())
- {
- QStringList strList = e->mimeData()->text().split(QRegExp("\\s+"),QString::SkipEmptyParts);
- QPoint pos = e->pos();
-
- foreach(QString str, strList) {
- DragLabel *dragLabel = new DragLabel(str,this);
- dragLabel->move(pos);
- dragLabel->show();
- pos += QPoint(dragLabel->width(),0);
- }
- if (children().contains(e->source())) {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else {
- e->acceptProposedAction();
- }
- }
- else {
- e->ignore();
- }
- }
上代码的if判断可知,拖拽文本不仅支持自定义的格式hasFormat("Drag-Text"),而且还支持简单的文本格式e->mimeData()->hasText(),因此其他的文本也可来回共享(图片仅支持自己的格式)。
3、拖拽图标
(1)同一实例程序拖拽(移动)
![](https://img-blog.csdn.net/20140701105344702?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- void DragIcon::mousePressEvent(QMouseEvent * e)
- {
- if(e->button() == Qt::LeftButton)
- startPos = e->pos();
- }
-
- void DragIcon::mouseMoveEvent(QMouseEvent * e)
- {
- if (!e->buttons()&Qt::LeftButton)
- return;
- if ((e->pos() - startPos).manhattanLength() < QApplication::startDragDistance())
- return;
-
- QPixmap pix = *pixmap();
-
- QByteArray data;
- QDataStream stream(&data,QIODevice::WriteOnly);
- stream << pix << QPoint(e->pos()-rect().topLeft());
- QMimeData *mimeData = new QMimeData;
- mimeData->setData("Drag-Icon",data);
-
- QDrag *drag = new QDrag(this);
- drag->setMimeData(mimeData);
- drag->setHotSpot(QPoint(e->pos() - rect().topLeft()));
- drag->setPixmap(pix);
-
- hide();
-
- Qt::DropAction dropAction = drag->start(Qt::CopyAction | Qt::MoveAction);
-
- if (dropAction == Qt::MoveAction)
- close();
- else
- show();
- }
- void DragWidget::dragEnterEvent(QDragEnterEvent *e)
- {
- if (e->mimeData()->hasText() || e->mimeData()->hasFormat("Drag-Icon"))
- {
- if(children().contains(e->source()))
- {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else
- e->acceptProposedAction();
- }
- }
-
- void DragWidget::dragMoveEvent(QDragMoveEvent *e)
- {
- if (e->mimeData()->hasText() || e->mimeData()->hasFormat("Drag-Icon"))
- {
- if(children().contains(e->source()))
- {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else
- e->acceptProposedAction();
- }
- }
在本窗口的右侧组件中可以来回拖放图片,因改程序自定义了图片格式hasFormat("Drag-Icon"),因此其他的图片无法拖入。
(2)不同实例程序拖拽(复制)
![](https://img-blog.csdn.net/20140701110958815?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvdGFpeWFuZzE5ODc5MTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast)
- void DragWidget::dropEvent(QDropEvent *e)
- {
- if (e->mimeData()->hasFormat("Drag-Icon")) {
- QByteArray data = e->mimeData()->data("Drag-Icon");
- QDataStream stream(&data,QIODevice::ReadOnly);
- QPixmap pix;
- QPoint offset;
- stream >> pix >> offset;
-
- DragIcon *icon = new DragIcon(pix,this);
- icon->move(e->pos() - offset);
- icon->resize(50, 50);
- icon->show();
- if (children().contains(e->source())) {
- e->setDropAction(Qt::MoveAction);
- e->accept();
- }
- else e->acceptProposedAction();
- }
-
- }
四、总结
(1)本文仅简单总结,还可以扩展到类似于剪贴板的机制,拖拽文字可以加入字符集的转换,拖拽图片可以考虑外部图片的转换,还可以扩展到文件的拖拽。
(2)对部分代码的理解也是不太深入,还得进一步深究。
(3)源码已经打包上传到csdn上可登录下载(http://download.csdn.net/detail/taiyang1987912/7574413)。