Qt学习之路28--拖放事件

什么是拖放事件?

将一个文件往应用程序窗口里拖放时,操作系统能感知这个动作,并发送系统消息到应用程序后会产生一个拖放事件。
拖放事件分为两部分,将文件拖到窗口内部和松开鼠标。

怎么处理拖放事件?

  • 所有的QWidget对象都能处理拖放事件
  • 通过两个函数实现事件处理(分别对应拖和放):
    -void dragEnterEvent(QDragEnterEvent* event);这个事件处理程序在拖动过程中被调用,当鼠标拖动文件进入当前QWidget对象中时,拖拽事件通过参数event进行传递,如果拖拽事件被忽略后,当前QWidget对象就不会收到任何相关消息。
    -void dropEvent(QDropEvent* event) ;当拖拽被放下时将会产生QDropEvent事件,通过参数event进行事件传递。
    所以在拖放事件的处理上需要对拖和放两个动作进行处理。

拖放事件中的QMimeData

  • QMimeData是Qt中的多媒体数据类
  • 拖放事件通过QMimeData对象传递数据
  • QMimeData支持多种不同类型的多媒体数据,包括文本、html数据、合法路径、图片、颜色等。
  • 操作QMimeData数据对象的常用函数:
    Qt学习之路28--拖放事件_第1张图片
    包含测试MIME数据的类型、获取MIME数据和设置MIME数据。

自定义拖放事件步骤

  • 首先需要对接收拖放事件的对象调用setAcceptDrops(bool on);该属性作用为设置QWidget对象是否可以接收QDropEvent事件,默认为不接收此事件。注意:不要在拖放事件处理函数里面修改该属性。
  • 重写dragEnterEvent(QDragEnterEvent* event)事件处理函数,并判断MIME数据类型
    -期望数据:调用event->acceptProposedAction()接收该数据
    -其他数据:调用event->ignore()忽略该数据
  • 重写dropEvent(QDropEvent* event)事件处理函数,并判断MIME数据类型
    -期望数据:从对象中获取MIME数据并进行处理
    -其他数据:调用e->ignore()忽略该数据

自定义拖放事件试验

自定义一个Widget类,公有继承自QWidget。
其头文件如下:

class Widget : public QWidget
{
    Q_OBJECT
protected:
    void dragEnterEvent(QDragEnterEvent* e);//重新实现两个事件处理函数
    void dropEvent(QDropEvent* e);

public:
    Widget(QWidget *parent = 0);
    ~Widget();
};

源文件如下:
根据实际使用情况添加相应的头文件。

Widget::Widget(QWidget *parent) : QWidget(parent)
{
    setAcceptDrops(true);//set this widget able to accept drop events
}

void Widget::dragEnterEvent(QDragEnterEvent* e)//拖
{
    if(e->mimeData()->hasUrls())//判断数据类型
    {
        e->acceptProposedAction();//接收该数据类型拖拽事件
    }
    else
    {
        e->ignore();//忽略
    }
}

void Widget::dropEvent(QDropEvent* e)//放
{
    if(e->mimeData()->hasUrls())//处理期望数据类型
    {
        QList<QUrl> list = e->mimeData()->urls();//获取数据并保存到链表中
        for(int i = 0; i < list.count(); i++)
        {
            qDebug() << list[i].toLocalFile();
        }
    }
    else
    {
        e->ignore();
    }
}

Qt学习之路28--拖放事件_第2张图片

通过将选中的文件条目拖拽到Widget窗口并松开鼠标后就会触发拖放事件,根据代码的处理方式就是将所获得的路径通过qDebug()打印出来。

扩展:文本编辑器中的拖放事件

Qt学习之路28--拖放事件_第3张图片
可以通过重写拖拽事件处理函数增加拖拽文件到主窗口后打开文件的功能。

解决方案:

  • 调用主窗口对象的setAcceptDrops()函数
  • 重写dragEnterEvent(QDragEnterEvent* event)函数并判断MIME数据类型
  • 重写dropEvent(QDropEvent* event)函数判断MIME数据类型后打开文件
  • 具体实现和之前试验代码框架基本一样,不同的只是dropEvent函数里的处理形式不同。
void MainWindow::dropEvent(QDropEvent* e)
{
  if( e->mimeData()->hasUrls() )
   {
       QList<QUrl> list = e->mimeData()->urls();
       QString path = list[0].toLocalFile();
       QFileInfo fi(path);
       if( fi.isFile() )
       {
           preEditorChange();//保存编辑器中未保存的内容
           if( !m_isTextChanged )//文件未修改
           {
               openFileToEditor(path);//打开path对应的文件
           }
       }
       else
       {
           showErrorMessage("Cannot open a folder!");
       }
   }
   else
   {
       e->ignore();
   }
}

小结

  • 拖拽事件分为两部分:拖和放。
  • 所有的QWidget对象都能处理拖拽事件。
  • 通过三部曲处理自定义拖拽事件。

你可能感兴趣的:(Qt)