加载中…
正文 字体大小:

Qt学习系列之五:实现Drag and Drop的最简模型

(2009-06-09 22:54:12)
标签:

qt

drag

and

drop

拖拽

it

分类: 技术文章
在做图形界面时,我们经常会遇到需要实现Drag & Drop的效果,即拖拽效果,例如在实现拼图游戏的时候,我们就需要能够用鼠标拖拽拼图块,然后在我们想要停下的地方松开鼠标左键,从而将该图块放置在我们指定的地方。
Qt对拖拽的支持是非常强大和全面的,但是无论是Qt自身所带的Demo还是网上的相关资料,都感觉复杂了,太多和Drag & Drop无必需联系的细节掩盖了改效果的实现主线。下面我实现了一个Drag & Drop效果的最简模型。
程序运行效果是,在对话框中会出现一只可爱的企鹅(item),然后可以通过鼠标左键对该企鹅进行拖拽(Drag & Drop)。
首先,我们需要从QLabel继承一个我们自己的类DragItem。之所以选择QLabel是因为该类比较基本,而且能够很好的、无边框得存在于对话框中。实现该类最重要的也是必须的一点是,要在其构造函数中创建一个QImage对象,然后通过setPixmap函数将其选入,代码如下:
DragItem::DragItem(QWidget *parent):QLabel(parent)
{
    QImage image (128, 128, QImage::Format_ARGB32);
    if (image.load("../icon.png") == false)
        QMessageBox::warning(this, "ERROR", "Load image error!");
    setPixmap (QPixmap::fromImage(image));
}
然后,我们还需要一个对话框用于显示该item,也就是起到容器的作用。该对话框类必须要在其构造函数中通过setAcceptDrops函数,将其AcceptDrops属性设置为true,否则无法进行拖拽。构造函数如下:
Dialog::Dialog(QWidget *parent): QDialog(parent), ui(new Ui::Dialog)
{
   DragItem *item = new DragItem (this);
   item->setAttribute(Qt::WA_DeleteOnClose);
   item->show();
   setMinimumSize (400, 400);
   setWindowTitle (tr("Drag & Drop Simplest Demo"));
   setAcceptDrops (true);
   ui->setupUi(this);
}
然后关键就是实现三个事件响应函数,分别是:
void dragEnterEvent (QDragEnterEvent *event);
void dropEvent (QDropEvent *event);
void mousePressEvent (QMouseEvent *event);
dragEnterEvent函数在鼠标拖拽物件进入该对话框范围内是被触发;dropEvent是当用户在对话框范围内松开鼠标左键结束拖拽时被触发;mousePressEvent,顾名思义,就是当鼠标被按下(无论是左键、右键还是中轮)被触发。我们需要在mousePressEvent响应函数内,创建QMimeData数据对象,然后用QDrag实现最终的拖拽效果。mousePressEvent负责对传入的QMimeData进行辨析,如果是我们想要的拖拽文件类型,就接受这个拖拽信息,否则予以忽略。dropEvent要做的是当拖拽结束,我们需要在新的位置再创建一个item对象,而将原先位置的item删除(或者关闭),通知完全将原有的item属性复制到新创建的item对象中。
这三个函数的实现代码如下:
void Dialog::dragEnterEvent (QDragEnterEvent *event)
{
   if (event->mimeData()->hasFormat("application/x-draganddrop"))
      event->accept();
   else
      event->ignore();
}

void Dialog::dropEvent (QDropEvent *event)
{
   if (event->mimeData()->hasFormat("application/x-draganddrop"))
   {
      const QMimeData *mimeData = event->mimeData();
      QByteArray exData = mimeData->data("application/x-draganddrop");
      QDataStream dataStream (&exData, QIODevice::ReadOnly);
      QPoint pos;
      dataStream>>pos;
      DragItem *item = new DragItem (this);
      item->setAttribute (Qt::WA_DeleteOnClose);
      item->move(event->pos()-pos);
      item->show();
   }
}

void Dialog::mousePressEvent (QMouseEvent *event)
{
   if (event->button() != Qt::LeftButton)
   {
      event->ignore();
      return;
   }
   DragItem *item = (DragItem *)(this->childAt(event->pos()));
   if (item == NULL)
   {
      event->ignore();
      return;
   }
   else
   {
      QMimeData *mimeData = new QMimeData;
      QByteArray exData;
      QDataStream dataStream (&exData, QIODevice::WriteOnly);
      dataStream<<event->pos() - item->pos();
      mimeData->setData("application/x-draganddrop", exData);
      mimeData->setText(tr("Drag and Drop"));
      QDrag *drag = new QDrag (this);
      drag->setMimeData(mimeData);
      drag->setPixmap(*(item->pixmap()));
      drag->setHotSpot(event->pos() - item->pos());
      item->hide();
      if (drag->exec(Qt::MoveAction) == Qt::MoveAction)
         item->close();
      else
         item->show();
   }
}

0

阅读 评论 收藏 转载 喜欢 打印举报
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4006900000 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有