qtabwidget切换tab_qt tablewidget

qtabwidget切换tab_qt tablewidget0.实现效果(声明:这只是个测试,不是很满意,放着也没用就分享下)实现效果GIF:完整代码链接:https://github.com/gongjianbo/MyTestCode/tree/master/Qt/MyTabWidget相关参考:https://www.cnblogs.com/findumars/p/5175984.html相关参考:https://github.com/MRXY001/Qt-DragableTabWidget1.实现过程QTabWidget的Tab

大家好,又见面了,我是你们的朋友全栈君。如果您正在找激活码,请点击查看最新教程,关注关注公众号 “全栈程序员社区” 获取激活教程,可能之前旧版本教程已经失效.最新Idea2022.1教程亲测有效,一键激活。

Jetbrains全系列IDE稳定放心使用

0.实现效果

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

实现效果GIF:

qtabwidget切换tab_qt tablewidget

完整代码链接: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);
    //这里套一个自定义标题栏的窗口给page
    MyTabPopup *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));

    //判断独立窗口是否拖回tab
    connect(pop,&MyTabPopup::dragRelease,this,[=](const QPoint &pos){
        const QPoint bar_pos=tabBar()->mapFromGlobal(pos);
        //如果又拖回了tabbar范围内,就把widget取出来放回tab
        if(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();
}

 

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。

发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/190167.html原文链接:https://javaforall.net

(0)
全栈程序员-站长的头像全栈程序员-站长


相关推荐

  • H3C交换机常用命令大全

    H3C交换机常用命令大全一.用户配置:system-view[H3C]superpasswordH3C设置用户分级密码[H3C]undosuperpassword删除用户分级密码[H3C]localuserbigheap1234561Web网管用户设置,1(缺省)为管理级用户,缺省admin,admin[H3C]undolocaluserbigheap删…

    2022年6月20日
    34
  • #1032 : 最长回文子串

    #1032 : 最长回文子串#1032:最长回文子串时间限制:1000ms单点时限:1000ms内存限制:64MB描述   小Hi和小Ho是一对好朋友,出生在信息化社会的他们对编程产生了莫大的兴趣,他们约定好互相帮助,在编程的学习道路上一同前进。   这一天,他们遇到了一连串的字符串,于是小Hi就向小Ho提出了那个经典的问题:“小Ho,你能不能分别在

    2022年6月3日
    29
  • sqrt mysql_MySQL中的SQRT函数的使用方法「建议收藏」

    sqrt mysql_MySQL中的SQRT函数的使用方法「建议收藏」推荐:MySQL中的SUM函数使用教程这篇文章主要介绍了MySQL中的SUM函数使用教程,是MySQL入门学习中的基础知识,需要的朋友可以参考下MySQL的SUM函数是用来找出记录中各种的字段的总和。要了解SUM函数考虑EMPLOYEE_TBL表具有以下记录:?现在,假设根据上面的表想来计算所有的dialy_typing_pages的总数这篇文章主要介绍了详解MySQL中的SQRT函数的使…

    2022年5月27日
    34
  • 简述分组密码的加密分组链接模式的工作原理及其特点(密码学移位密码加密解密)

    密钥生成如何安全地生成密钥。即如何生成可信任的密钥,保证用户得到的密钥是安全的,生成密钥的机器或程序是可信的。 如何生成安全的密钥。安全的密钥没有统一准确的定义,但一般来说是指密钥抗猜测和抗穷举等针对密钥攻击的能力。涉及密钥长度和密钥强弱的问题。分组加密对称加密算法按其加密数据的方式一般来说可以分成两种类型:分组加密和序列加密。 分组加密又称为块加密,是将要处理的数据分成固定的长度,然后在这固定长度的数据上使用密码算法进行计算。 序列加密模式又称为流加密方式,是对要处理的数据按位(或字

    2022年4月13日
    153
  • 使用iframe框架后的页面,执行跳转命令,目标页面内嵌至iframe的子页面的解决方法

    使用iframe框架后的页面,执行跳转命令,目标页面内嵌至iframe的子页面的解决方法问题描述 nbsp nbsp nbsp nbsp 在做项目的过程中 需要完成修改密码后重新登录的功能 但是前端页面使用了 IFrame 的框架 修改页面内嵌在的 index html 中 重新登录的页面就内嵌到原来的页面中 问题如图所示 nbsp 修改密码成功后 nbsp 出现问题 修改密码页面跳转到的登录页面内置到了子页面中 nbsp 登录后出现了如下页面 nbsp 前端使用的是 AngularJs 后台使用的 sp

    2025年8月23日
    2
  • 像Excel一样使用python进行数据分析

    像Excel一样使用python进行数据分析Excel是数据分析中最常用的工具,本篇文章通过python与excel的功能对比介绍如何使用python通过函数式编程完成excel中的数据处理及分析工作。在Python中pandas库用于数据处理

    2022年7月6日
    17

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注全栈程序员社区公众号