Qt之QAbstractItemView视图项拖拽(二)

一、需求说明   

    上一篇文章Qt之QAbstractItemView视图项拖拽(一)讲述了实现QAbstractItemView视图项拖拽的一种方式,是基于QDrag实现的,这个类是qt自己封装好了的,所以可定制性也就没有了那么强,最明显的是,这个类在执行exec方法后,mouse系列的回调接口就被阻塞了,随之而来的问题就是拖拽时item项没有了hover特性,为了解决这个问题,我们就不能使用QDrag类来实现拖拽了,这也是这篇文章我要讲述的内容。

二、效果展示  

    如图1是demo的效果展示,比较丑,如果加上优秀的qss,那必然能让人眼前一亮

图1 ListWidget拖拽


三、实现思路

  1. 继承QListWidget类,重写其鼠标多拽时几个虚方法,分别是mousePressEvent(鼠标按下),mouseMoveEvent(鼠标移动),mouseReleaseEvent(鼠标弹起)等,当然还包括一些辅助的回调方法enterEvent和leaveEvent。
  2. 鼠标按下时,记录鼠标按下位置和鼠标点击项
  3. 鼠标移动时移动插入项标示和item项快照位置,并修改鼠标形状
  4. 最后鼠标释放时,判断如果需要更新拖拽项位置,那么把原有项删除,并构造新的项插入到目标位置

      上边的几个步骤描述都是在mouse系列的回到接口中发生的,再也没有QDrag的事儿啦。当然这个mouse方法中需要做一些鼠标状态维护等。

四、代码说明

    1、重要的类和上一篇文章中的一样,忘记的小伙伴可以到上一篇文章查看,或者猛戳Qt之QAbstractItemView视图项拖拽(一)
    2、下面就直接上代码
    a、记录鼠标按下时信息

 1 void DragList::mousePressEvent(QMouseEvent * event)
 2 {
 3     if (event->button() == Qt::LeftButton)
 4     {
 5         m_LeftPress = true;
 6         startPos = event->pos();
 7         dragItem = itemAt(event->pos());
 8     }
 9 
10     QListWidget::mousePressEvent(event);
11 }

    b、鼠标移动时维护鼠标状态、快照位置和插入表示位置

 1 void DragList::mouseMoveEvent(QMouseEvent * event)
 2 {
 3     QListWidgetItem * item = itemAt(event->pos());
 4     if (dragItem == nullptr)
 5     {
 6         dragItem = itemAt(event->pos());
 7     }
 8 
 9     if (m_ShotPicture == nullptr)
10     {
11         InitShotLabel();
12     }
13     if (m_ShotLine == nullptr)
14     {
15         InitShotLine();
16     }
17 
18     QRect rect = visualItemRect(dragItem);
19     if (ListItem * hoverWidget = ItemWidget(item))
20     {
21         QRect hoverRect = visualItemRect(item);
22         QPoint pos = hoverWidget->mapFromParent(event->pos());
23         if (hoverRect.size().height() / 2 < pos.y())
24         {
25             m_ShotLine->move(mapToGlobal(QPoint(2, hoverRect.y() + hoverRect.height() + 1)));
26         }
27         else
28         {
29             m_ShotLine->move(mapToGlobal(QPoint(2, hoverRect.y() + 1)));
30         }
31         
32         m_ShotLine->setVisible(hoverRect.contains(event->pos()));
33     }
34 
35     if (ListItem * newWidget = ItemWidget(dragItem))
36     {
37         m_ShotPicture->move(mapToGlobal(event->pos() - newWidget->mapFromParent(startPos)));
38         if (rect.contains(event->pos()) || event->pos().isNull())
39         {
40             setCursor(Qt::ForbiddenCursor);
41         }
42         else
43         {
44             setCursor(Qt::ArrowCursor);
45         }
46         if (m_ShotPicture->isHidden())
47         {
48             m_ShotPicture->show();
49         }
50     }
51 
52 
53 //    QListWidget::mouseMoveEvent(event);
54 }

    c、鼠标释放时处理拖拽结果

 1 void DragList::mouseReleaseEvent(QMouseEvent * event)
 2 {
 3     if (event->button() == Qt::LeftButton)
 4     {
 5         m_LeftPress = false;
 6         if (m_ShotPicture)
 7         {
 8             m_ShotPicture->close();
 9             m_ShotPicture->deleteLater();
10             m_ShotPicture = nullptr;
11         }
12         if (m_ShotLine)
13         {
14             m_ShotLine->close();
15             m_ShotLine->deleteLater();
16             m_ShotLine = nullptr;
17         }
18         MouseRelease(event);
19     }
20 
21     setCursor(Qt::ArrowCursor);
22 
23     QListWidget::mouseReleaseEvent(event);
24 }

    d、初始化跟随鼠标移动的快照,并把当前拖拽的窗口截图设置给快照

 1 void DragList::InitShotLabel()
 2 {
 3     m_ShotPicture = new QLabel;
 4     m_ShotPicture->setWindowOpacity(0.95);
 5     m_ShotPicture->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
 6     m_ShotPicture->setAttribute(Qt::WA_TransparentForMouseEvents, true);
 7 
 8     if (ListItem * oldWidget = ItemWidget(dragItem))
 9     {
10         m_ShotPicture->setPixmap(oldWidget->grab());
11         m_ShotPicture->resize(visualItemRect(dragItem).size());
12     }
13     m_ShotPicture->show();
14 }

    e、初始化鼠标插入位置标示

 1 void DragList::InitShotLine()
 2 {
 3     m_ShotLine = new QLabel;
 4     m_ShotLine->setObjectName(QStringLiteral("ShotLine"));
 5     m_ShotLine->setWindowFlags(Qt::FramelessWindowHint | Qt::Tool | Qt::WindowStaysOnTopHint);
 6     m_ShotLine->setAttribute(Qt::WA_TransparentForMouseEvents, true);
 7     m_ShotLine->setStyleSheet("QLabel#ShotLine{background:green;}");//用图片代替
 8     
 9     if (ListItem * oldWidget = ItemWidget(dragItem))
10     {
11     //    m_ShotLine->setPixmap(oldWidget->grab());
12         m_ShotLine->resize(visualItemRect(dragItem).size().width(), 2);
13     }
14     m_ShotLine->show();
15 }

    f、鼠标弹起具体处理函数

 1 void DragList::MouseRelease(QMouseEvent * event)
 2 {
 3     QListWidgetItem * item = itemAt(event->pos()); 
 4     if (item == nullptr || item == dragItem)
 5     {
 6         return;
 7     }
 8 
 9     int insertPos = row(item);
10     if (ListItem * oldWidget = ItemWidget(item))
11     {
12         QPoint pos = oldWidget->mapFromParent(event->pos());
13         if (oldWidget->size().height() / 2 < pos.y())
14         {
15             insertPos += 1;
16         }
17     }
18 
19     if (dragItem)
20     {
21         if (ListItem * oldWidget = ItemWidget(dragItem))
22         {
23             QListWidgetItem * newItem = new QListWidgetItem;
24             ListItem * itemWidget = new ListItem;
25             itemWidget->SetData(oldWidget->GetData());
26 
27             insertItem(insertPos, newItem);
28             setItemWidget(newItem, itemWidget);
29 
30             setCurrentItem(newItem);
31 
32             oldWidget->deleteLater();
33         }
34 
35         dragItem = takeItem(row(dragItem));
36         if (dragItem)
37         {
38             delete dragItem;
39             dragItem = nullptr;
40         }
41     }
42 }

五、下载链接 

    Qt之QAbstractItemView视图项拖拽2 

六、相关文章

  自定义拖放数据:这篇文章是讲述怎么自定义QMimeData数据的,我使用的是其中第二个方法。

  Qt之QAbstractItemView视图项拖拽(一)

  Qt之QAbstractItemView选择无焦点

转载于:https://www.cnblogs.com/swarmbees/p/6055280.html

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/260169.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

电脑控制苹果手机_必备神器,电脑控制手机

序一款电脑端的神器&#xff0c;它可以任意的操纵你的手机。****QtScrcpy可以通过USB(或通过TCP/IP)连接Android设备&#xff0c;并进行显示和控制。不需要root权限。单个应用程序最多支持16个安卓设备同时连接。同时支持GNU/Linux&#xff0c;Windows和MacOS三大主流桌面平台。…

php未定义要怎样做,php-Behat-未定义的功能步骤

我设置了一个简单的测试场景来学习behat,但是我遇到了一些问题.我正在关注THIS教程.这是我的专题节目&#xff1a;Feature: showThis is a behat feature to test the article pages.##TODOScenario: I want to view a detailed article pageGiven I am logged inAnd Im on &qu…

CentOS 命令大全 (转)

1、查看系统使用端口并释放端口 [rootmy_nn_01 WEB-INF]# lsof -w -n -i tcp:80 COMMAND PID USER FD TYPE DEVICE SIZE NODE NAME java 24065 root 34u IPv6 269149 TCP *:http (LISTEN) [rootmy_nn_01 WEB-INF]# kill -9 24065 2、以KB/MB形式显示文件列表…

微信接口改良

之前公司微信开发的时候 写了个微信的接口改良版,当然好多想改进的都没改。。大概是太懒了 &#xff08;囧 /*** Created by DFH on 13-12-16.*//*--htmlvar shareData {//分享展示图片地址 **必须"imgUrl": "a.jpg",//分享至朋友圈链接 **必须&q…

生活大爆炸版石头剪刀布

题目描述 Description石头剪刀布是常见的猜拳游戏&#xff1a;石头胜剪刀&#xff0c;剪刀胜布&#xff0c;布胜石头。如果两个人出拳一样&#xff0c;则不分胜负。在《生活大爆炸》第二季第8集中出现了一种石头剪刀布的升级版游戏。升级版游戏在传统的石头剪刀布游戏的基础上&…

oracle18c卸载方法,在debian 10上安装和卸载oracle数据库快捷版18c第4版

安装oracle-xe-18c的步骤此安装向导依赖软件包alien。由于oracle并未提供oracle-xe-18c的deb包&#xff0c;故需要通过alien命令将oracle-xe-18c的rpm格式的安装包导出新的deb格式的安装包&#xff1a;sudo alien --scripts -d oracle-database-xe-18c-1.0-1.x86_64.rpm相应rpm…

解决:缺少aclocal、autoconf、automake

下载三个包&#xff1a;autoconf-2.68.tar.bz2、automake-1.11.1.tar.bz2、m4-1.4.14.tar.bz2 1、su - root 2、tar xjf XXXXX.tar.bz2 3、cd m4/ 4、./configure make make install 5、cd autoconf/ 6、./configure make make install 7、cd automake/ 8、./configure…

jquery事件 on(),live(),delegate(),blind()

jQuery推出on()的目的有2个&#xff0c;一是为了统一接口&#xff0c;二是为了提高性能&#xff0c; 所以从现在开始用on()替换bind(), live(), delegate吧。 尤其是不要再用live()了&#xff0c;因为它已经处于不推荐使用列表了[1.7已经被删除]。 如果只绑定一次事件&#xff…

Swift 开发的工具类,主要是提供正则表达式及其它,Github会长期维护

直接访问 GitHub 看代码 YYGRegular 我是&#xff1a; 语歌复制代码It is a regular expression used on iOS, which implement by Swift 这是一个基于swift快捷开发的扩展类&#xff0c;目前的涵盖内容包括详细打印&#xff0c;正则表达式&#xff0c;会经常维护 介于是增加更…

用python庆祝生日_生日到底该过阴历还是阳历好呢?不是迷信,都怪我们大意!...

过生日到底该过阴历还是阳历&#xff1f;答案说出来你可能都不信在我们国家&#xff0c;过生日有两种不同的方式&#xff0c;因为有两种不同的日子的计算方式&#xff0c;分为阴历和阳历。一般来说&#xff0c;在农村和一些比较落后的地方&#xff0c;人们习惯于用阴历来计算生…

websphere jndi oracle,websphere7.0获得JNDI连接报invalid username/password

Exception in thread "P497968:O0:CT" java.sql.SQLException: ORA-01017: invalid username/password; logon deniedDSRA0010E: SQL 状态&#xff1a;72000&#xff0c;错误码&#xff1a;1,017at oracle.jdbc.driver.SQLStateMapping.newSQLException(SQLStateMapp…

WSS3.0自带数据库可以使用SQL 2005 Server Management Studio来管理

默认情况下&#xff0c;安装完WSS3.0后&#xff0c;会自动安装一个自带的SQL Server 2005 Embedded Edition数据库&#xff0c;但是此数据库却没有管理工具,不像安装SQL 2005其它版本会有管理工具。如果你要管理数据库&#xff0c;这时怎么办呢。经过俺试了一上午了&#xff0c…

CPU的高速缓存存储器知识整理

基于缓存的存储器层次结构 基于缓存的存储器层次结构行之有效&#xff0c;是因为较慢的存储设备比较快的存储设备更便宜&#xff0c;还因为程序往往展示局部性&#xff1a; 时间局部性&#xff1a;被引用过一次的存储器的位置很可能在不远的将来被再次引用。 空间局部性&#x…

uniapp光标自动定义到文本框_word技巧自动生成毕业论文目录

一篇word文档&#xff0c;内容有大的章&#xff0c;小的节。如何把章节抽出来生成目录&#xff1f;WORD →点击需要插入的地方 → 插入菜单 → 索引和目录 → 目录 → 确定。1 创建标题目录Word 一般是利用标题或者大纲级别来创建目录的。因此&#xff0c;在创建目录之前&#…

JSTL

2019独角兽企业重金招聘Python工程师标准>>> 说明 JSTL 是 JAVA 中的一个定制标记库集。实现了JSP页面中代码的复用&#xff0c;增加了JSP页面的可读性&#xff0c;方便查看和参与开发 使用 1.下载地址 http://archive.apache.org/dist/jakarta/taglibs/standard/bi…

[jQuery] event.stopPropagation()报错

使用jQuery给一个事件加处理方法时&#xff0c;为了阻止一个事件向上冒泡&#xff0c;使用了event.stopPropagation()&#xff0c;但在IE下却报对象不支持此属性或方法的错误&#xff08;IE下是event. cancelBubbletrue&#xff09;&#xff0c;jQuery不是兼容各浏览器吗&#…

中科燕园arcgis外包----排水管网地理信息系统

项目背景 绍兴县是浙江省第一个“数字城管”试点城市&#xff0c;也是全国第一个“数字城管”县级城市。随着经济的飞速发展、城市化步伐的加快&#xff0c;以及城市规模的扩大和现代化程度的不断提高&#xff0c;作为城市重要基础设施的城市地下管线也越来越庞大、密集&#x…

自然语言0_nltk中文使用和学习资料汇总

sklearn实战-乳腺癌细胞数据挖掘&#xff08;博主亲自录制视频教程&#xff09; https://study.163.com/course/introduction.htm?courseId1005269003&utm_campaigncommission&utm_sourcecp-400000000398149&utm_mediumshare http://blog.csdn.net/huyoo/article/…

python实现深度优先搜索_python中的深度优先搜索算法

假设我有一个函数&#xff0c;它接受一个输入($x iui$)&#xff0c;然后经过一个循环并生成一系列输出($x{I&#xff0c;j}$)。然后&#xff0c;每个输出可以再次作为同一函数的输入&#xff0c;从而产生更多的输出($x{i&#xff0c;j&#xff0c;k}$)。我试图通过这个函数找到…

mysql函数移植到oracle,oracle到mysql的迁移,函数部分

to_date(?, YYYY-MM-DD HH24:MI:SS)"STR_TO_DATE(2003-15-10 00:00:00,%Y-%m-%d %H:%i:%s); //格式不对&#xff0c;会返回NULLto_char(create_time,yyyy-MM-dd)DATE_FORMAT(create_time,%Y-%m-%d)sysdatenow()或者CURRENT_TIMESTAMP //1997-12-15 23:50:26,建表的时…