0.实现效果

(声明:这只是个测试,不是很满意,放着也没用就分享下)

实现效果GIF:

完整代码链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/MyTabWidget

相关参考:https://www.cnblogs.com/findumars/p/5175984.html

相关参考:https://github.com/MRXY001/Qt-DragableTabWidget

1.实现过程

QTabWidget的Tab页签只能拖拽交换顺序,没有把Tab页拖入拖出的功能,我们可以通过继承QTabBar重新实现部分接口来实现这个功能。

首先是Tab页的拖出,主要通过QTabBar的鼠标事件来处理,如果拖出了QTabBar的区域就生成一个QDrag,用于显示Tab页的快照跟随鼠标。

当鼠标释放的时候,如果在QTabBar外部,则从QTabBar移除该页面,作为一个独立的窗口显示。

然后是Tab页的拖回,也是判断鼠标释放时的位置,如果在QTabBar范围,就添加到QTabBar中。

(1.目前这种方式效果不理想,太生硬了,没有浏览器Tab拖拽那种流畅的感觉,后期修改的话可能需要实时判断位置,而不是鼠标释放时才去处理;2.没有很好的利用Qt的drag drop事件接口,后期可以尝试下;3.QTabWidget很多默认的效果不大好,比如TabBar占据宽度居然是根据页签总宽而不是TabWidget占的宽度,这样判断区域也不方便,还有Tab页过多时的左右按钮也不好用,如果时间足够的话,最好重写)

主要代码片段:

void MyTabBar::mousePressEvent(QMouseEvent *event)
{QTabBar::mousePressEvent(event);if(event->button()==Qt::LeftButton&&currentIndex()>=0){//保存状态//pressPos=event->pos();theDragPress=true;}
}void MyTabBar::mouseMoveEvent(QMouseEvent *event)
{QTabBar::mouseMoveEvent(event);//move的时候button为NoButton,但是button's里有if(theDragPress&&event->buttons()){//是否脱离了tabbar的范围if(!theDragOut&&!contentsRect().contains(event->pos())){theDragOut=true;emit beginDragOut(this->currentIndex());//QDrag.exec后就不会触发release了,自己手动触发//不过他好像还是在鼠标弹起之后才会进行动画,待解决QMouseEvent *e=new QMouseEvent(QEvent::MouseButtonRelease,this->mapFromGlobal(QCursor::pos()),Qt::LeftButton,Qt::LeftButton,Qt::NoModifier);//mouseReleaseEvent(event);QApplication::postEvent(this,e);}}
}void MyTabBar::mouseReleaseEvent(QMouseEvent *event)
{QTabBar::mouseReleaseEvent(event);theDragPress=false;theDragOut=false;
}
void MyTabWidget::initTabBar()
{MyTabBar *bar=new MyTabBar(this);//setTabBar是protected成员函数,要使用就得继承setTabBar(bar);//点击页签上的关闭按钮时,触发信号connect(bar,&QTabBar::tabCloseRequested,this,&MyTabWidget::removeNormalIndex);//拖拽到外部-还未释放鼠标connect(bar,&MyTabBar::beginDragOut,this,[this,bar](int index){if(!indexValid(index))return;QWidget *drag_tab=this->widget(index);//固定tab就不让拖出if(!drag_tab||fixedPage.contains(drag_tab))return;//把当前页作为快照拖拽//尺寸加了标题栏和边框QPixmap pixmap(drag_tab->size()+QSize(2,31));pixmap.fill(Qt::transparent);QPainter painter(&pixmap);if(painter.isActive()){//这里想做标题栏贴在内容之上//但是没法获取默认标题栏的图像啊,就随便画一个矩形框//如果设置了外部主题颜色,需要改下QRect title_rect{0,0,pixmap.width(),30};painter.fillRect(title_rect,Qt::white);painter.drawText(title_rect,Qt::AlignLeft|Qt::AlignVCenter,"  "+drag_tab->windowTitle());painter.drawRect(pixmap.rect().adjusted(0,0,-1,-1));}painter.end();drag_tab->render(&pixmap,QPoint(1,30));QMimeData *mime=new QMimeData;QDrag *drag=new QDrag(bar);drag->setMimeData(mime);drag->setPixmap(pixmap);drag->setHotSpot(QPoint(10,0));//鼠标弹起后drag就释放了,这时候去判断是否拖拽到了外部connect(drag,&QDrag::destroyed,this,[=]{QPoint bar_point=bar->mapFromGlobal(QCursor::pos());//不在范围,拖出if(!bar->contentsRect().contains(bar_point)){popPage(drag_tab);}});drag->exec(Qt::MoveAction);});
}void MyTabWidget::popPage(QWidget *page)
{takeNormalPage(page);//这里套一个自定义标题栏的窗口给pageMyTabPopup *pop=new MyTabPopup(this);pop->setAttribute(Qt::WA_DeleteOnClose);pop->setContentWidget(page);pop->setWindowTitle(page->windowTitle());pop->resize(page->size());//拖出来的位置有点偏移pop->move(QCursor::pos()-QPoint(10,10));//判断独立窗口是否拖回tabconnect(pop,&MyTabPopup::dragRelease,this,[=](const QPoint &pos){const QPoint bar_pos=tabBar()->mapFromGlobal(pos);//如果又拖回了tabbar范围内,就把widget取出来放回tabif(tabBar()->contentsRect().contains(bar_pos)){QWidget *content=pop->getContentWidget();this->appendNormalPage(content);pop->disconnect();//关闭的时候会在原来的位置闪一下?pop->close();//this->activateWindow();}});pop->show();page->show();pop->activateWindow();pop->setFocus();
}

QTabWidget自定义,拖入拖出Tab页的简易实现相关推荐

  1. 谷歌浏览器打开标签会把之前的覆盖掉_Chrome 浏览器新更新解决了本地文件拖入导致的标签页意外关闭问题...

    原标题:Chrome 浏览器新更新解决了本地文件拖入导致的标签页意外关闭问题 这个问题之前相当让人头疼(至少对小编来讲是这样). 你有没有在 Google Chrome 浏览器上使用过拖放功能,但却发 ...

  2. 【IPhone】iTunes12.7 不能拖入或粘贴自定义铃声

    我是因为不知道咋的拖到了[我的设备上-音乐]里,结果应该是这个设备上已经有了同名的音乐所以不能拖入铃声里. 所以,把同名的删除,重新拖入或粘贴到铃声里即可

  3. [QT_015]Qt学习之基于条目控件的自定义特性(拖拽+右键菜单+样式)

    本文转自:<Qt编程指南>        作者:奇先生 Qt编程指南,Qt新手教程,Qt Programming Guide 本节介绍基于条目控件的定制特性,首先介绍条目的拖拽,列表控件. ...

  4. 360安全浏览器禁止拖入文件解决方法

    360安全浏览器/360急速浏览器不可以拖入文件解决方法 摘要:360安全浏览器/360急速浏览器禁止文件拖入浏览器进行打开.上传等操作的问题,按以下步骤1.2操作完即可解决(也适用于其他浏览器): ...

  5. jQuery学习笔记系列(一)——入口函数,jQuery对象和DOM对象,jQuery选择器、样式操作、效果(显示隐藏、滑入滑出、淡入淡出、自定义动画、停止动画队列)

    day01 - jQuery 学习目标: 能够说出什么是 jQuery 能够说出 jQuery 的优点 能够简单使用 jQuery 能够说出 DOM 对象和 jQuery 对象的区别 能够写出常用的 ...

  6. [Unity] AnimationEvent 因 Animator Controller 中 Transition 设置问题而不触发的快速解决办法:重新拖入 Animator 创建新 State

    这篇文章提出了一个 AnimationEvent 不触发的可能性:Animator Controller 中 Transition 设置问题 https://blog.csdn.net/qq_4173 ...

  7. 播放器SkeyeWebPlayer多分屏(九宫格)、拖动(拖入分屏播放)、双击分屏放大缩小等功能的使用

    免费视频直播.点播H5播放器SkeyeWebPlayer多屏(九宫格).双击分屏放大缩小.拖动(拖入分屏播放)等功能的使用. 1.SkeyeWebPlayer多屏(九宫格)布局切换,一般采用1.4.9 ...

  8. QTabWidget:转到某个tab页

    QT界面添加一个按钮,点击按钮,转到指定tab页. 新建一个QT项目,在设计器中分别选择QPushBtton.tab Widget.Label拖进.ui界面. 鼠标右键点击按钮转到槽函数,选择点击事件 ...

  9. Excel表格拖入Word中表格格式保持不变

    一.Excel表格拖入Word中表格格式保持不变 1.选中Excel中的表格,按住Ctrl键,拖动到word中即可. 二.word中的表格复制到Excel中表格格式保持不变 1.将word另存为网页格 ...

最新文章

  1. numpy 数组和矩阵的乘法
  2. Cissp-【第2章 资产安全】-2021-1-14(163页-185页)
  3. 常用数据库优化方案(三)
  4. std中稳定排序算法_敏哥:深挖亚马逊A9算法中的广告搜索排序
  5. activiti入门2流程引擎API和服务基础设施
  6. ansible内置模块
  7. JAVA程序设计----多线程(上)
  8. java连接mysql数据库C3P0入门
  9. Codeforces Round #197 (Div. 2): C. Xenia and Weights(记忆化搜索)
  10. Struts1 面试题目总结
  11. 分享十点C语言入门知识
  12. 10.1假期一半总结
  13. unsw计算机专业排名,新南威尔士大学UNSW计算机科学Computer Science专业排名第54位(2021年THE世界大学商科排名)...
  14. 爬取拉钩Java招聘数据
  15. 【Unity 框架】QFramework v1.0 使用指南 工具篇:06. UIKit 界面管理快速开发解决方案 | Unity 游戏框架 | Unity 游戏开发 | Unity 独立游戏
  16. 用C语言程序算交税,用C语言编写函数InComeTax计算七级累进税率的税后收入
  17. createjs php通信,快速入门createjs实例教程
  18. python网页爬虫菜鸟教程_【爬虫】菜鸟教程,支持翻页,存储
  19. 用Universe Sandbox模拟引力弹弓(地球+木星)
  20. stk 坐标系_STK用户手册.pdf

热门文章

  1. 计算机三级难度排行2019,2019计算机三级有用吗 计算机三级考试难不难
  2. android框架结构
  3. 微信小程序家庭记账本开发进度七
  4. 记录几个ubuntu无法开机的问题
  5. 安卓应用(APK)逆向工程
  6. UDP协议校验和的计算
  7. 前端Vue+ElementUI的Pagination分页组件实现分页展示 后端Spring Boot +Mybatis Plus实现分页接口
  8. 前端H5使用canvas画爱心以及笑脸
  9. Kinect openni 驱动
  10. 手动修复重建Windows 10系统EFI分区引导bootloader