qt -- QTabWidget 中支持拖拽TabBar项

目录

需求

效果

代码


需求

1、支持拖动交换TabBar标签位置
ui->tabWidget->setMovable(true);

2、支持将TabBar项拖出 QTabWidget 置顶显示

3、支持将拖出的TabBar项重新拖入QTabWidget中

效果

 

代码

MainWindow

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "custom_tabWidget/custom_tabwidget.h"
MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    m_pTabWidget = new CustomTabWidget(this);
    ui->verticalLayout->addWidget(m_pTabWidget);
    m_pTabWidget->addTab(new QTextEdit,"eidt 1");
    m_pTabWidget->addTab(new QTextEdit,"eidt 2");
    m_pTabWidget->addTab(new QTextEdit,"eidt 3");
    m_pTabWidget->addTab(new QTextEdit,"eidt 4");
}

MainWindow::~MainWindow()
{
    delete ui;
}

/*************************************/

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTextEdit>
namespace Ui {
class MainWindow;
}

class CustomTabWidget;
class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    CustomTabWidget* m_pTabWidget;
};

#endif // MAINWINDOW_H
CustomTabBar
#ifndef CUSTOM_TABBAR_H
#define CUSTOM_TABBAR_H

#include <QTabBar>
#include <QObject>
#include <QPoint>
#include <QMouseEvent>

class CustomTabBar : public QTabBar
{
    Q_OBJECT
public:
    CustomTabBar(QWidget *parent = nullptr);
    ~CustomTabBar();

protected:
    void mousePressEvent(QMouseEvent *event);
    void mouseMoveEvent(QMouseEvent *event);
    void mouseReleaseEvent(QMouseEvent *event);

signals:
    void signalStartDragTab(int);
    void signalStopDrapTab();
private:
    bool m_bPressFlag;
    QPoint m_pointPress;
    QPoint m_pointRelease;
};

#endif // CUSTOM_TABBAR_H


/******************************/
#include "custom_tabbar.h"

CustomTabBar::CustomTabBar(QWidget *parent):QTabBar(parent)
{
    m_bPressFlag = false;
    setMovable(true);
    //this->setAcceptDrops(true);
}

CustomTabBar::~CustomTabBar()
{

}

void CustomTabBar::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton && currentIndex() >= 0)
    {
        m_bPressFlag = true;
        m_pointPress = event->pos();
    }
    QTabBar::mousePressEvent(event);
}

void CustomTabBar::mouseMoveEvent(QMouseEvent *event)
{
    if(m_bPressFlag && event->buttons()) {
        if(qAbs(m_pointPress.y() - event->pos().y()) > this->height() &&
           !tabRect(this->currentIndex()).contains(event->pos())) {
            m_bPressFlag = false;
            if(this->count() != 1) {
                emit signalStartDragTab(this->currentIndex());
                emit signalStopDrapTab();
            }
        }
    }
    QTabBar::mouseMoveEvent(event);
}

void CustomTabBar::mouseReleaseEvent(QMouseEvent *event)
{
    m_bPressFlag = false;
    m_pointRelease = event->pos();
    if (qAbs(m_pointPress.y() - m_pointRelease.y()) > this->height())
    {
//        if(this->count() != 1) {
//            emit signalStopDrapTab();
//        }
    }
    QTabBar::mouseMoveEvent(event);
}
CustomTabWidget
#ifndef CUSTOM_TABWIDGET_H
#define CUSTOM_TABWIDGET_H

#include <QDrag>
#include <QTabWidget>
#include <QMimeData>
#include <QDragEnterEvent>
#include <QMouseEvent>
class CustomTabBar;
class CustomPopupPage;
class CustomTabWidget : public QTabWidget
{
public:
    CustomTabWidget(QWidget *parent = nullptr);
    ~CustomTabWidget();
private:
    void init();

protected:
//    void dragEnterEvent(QDragEnterEvent *event);
//    void dragMoveEvent(QDragMoveEvent *event);
//    void dropEvent(QDropEvent *event);

//    void mousePressEvent(QMouseEvent *event);
//    void mouseMoveEvent(QMouseEvent *event);
//    void mouseReleaseEvent(QMouseEvent *event);
private slots:
    void addTabPage(const QPoint &pos);
private:
    CustomTabBar* m_pTabBar;
    QWidget* m_pDragTab;   //拖拽显示的页面
    int m_nTabIndex;       //标签索引
    QString m_strTitle;    //标签标题
    CustomPopupPage* m_pPopupPage;
};

#endif // CUSTOM_TABWIDGET_H


/*******************************/

#include "custom_tabwidget.h"
#include "custom_tabbar.h"
#include "custom_popup_page.h"
CustomTabWidget::CustomTabWidget(QWidget *parent):
    QTabWidget(parent),
    m_pTabBar(nullptr)
{
    init();
}

CustomTabWidget::~CustomTabWidget()
{

}

void CustomTabWidget::init()
{
    this->setAcceptDrops(true);
    m_pTabBar = new CustomTabBar(this);

    this->setTabBar(m_pTabBar);

    //拖拽窗口
    connect(m_pTabBar, &CustomTabBar::signalStartDragTab, this, [&](int index) {

        m_nTabIndex = index;
        m_strTitle = this->tabText(index);
        m_pDragTab = this->widget(index);

    });

    //拖拽释放窗口显示
    connect(m_pTabBar, &CustomTabBar::signalStopDrapTab, this, [&]() {

//        this->removeTab(m_nTabIndex);
        m_pPopupPage = new CustomPopupPage(this);
        connect(m_pPopupPage, &CustomPopupPage::signalDragRelease, this, &CustomTabWidget::addTabPage);
        connect(m_pPopupPage, &CustomPopupPage::signalAddTab, this, [&](){
            const int index = this->insertTab(m_nTabIndex, m_pDragTab, m_strTitle);
            //切换为当前新增页
            this->setCurrentIndex(index);
        });
        m_pPopupPage->setContentWidget(m_pDragTab);
        m_pPopupPage->setWindowTitle(m_strTitle);
        m_pPopupPage->resize(m_pDragTab->size());
        m_pDragTab->show();
        m_pPopupPage->exec();

    });
}

void CustomTabWidget::addTabPage(const QPoint &pos)
{
    const QPoint bar_pos = this->tabBar()->mapFromGlobal(pos);

    //如果又拖回了tabbar范围内,把widget取出来放回tab
    if(this->tabBar()->contentsRect().contains(bar_pos))
    {
        const int index = this->insertTab(m_nTabIndex, m_pPopupPage->getContentWidget(), m_pPopupPage->windowTitle());
        //切换为当前新增页
        this->setCurrentIndex(index);
        m_pPopupPage->disconnect();
        m_pPopupPage->close();
    }
}
CustomPopupPage
#ifndef CUSTOM_POPUP_PAGE_H
#define CUSTOM_POPUP_PAGE_H

#include <QObject>
#include <QWidget>
#include <QDialog>
#include <QEvent>
#include <QMouseEvent>
#include <QVBoxLayout>
#include <QCloseEvent>

class CustomPopupPage : public QDialog
{
    Q_OBJECT
public:
    CustomPopupPage(QWidget *parent = nullptr);
    ~CustomPopupPage();
    void setContentWidget(QWidget *page);
    QWidget* getContentWidget();

protected:
    bool event(QEvent *event);
    void closeEvent(QCloseEvent *event);
signals:
    void signalDragRelease(const QPoint &globalPos);
    void signalAddTab();
private:
    QWidget * m_page;
};

#endif // CUSTOM_POPUP_PAGE_H


/******************************************************/

#include "custom_popup_page.h"

CustomPopupPage::CustomPopupPage(QWidget *parent):
    QDialog(parent)
{
    m_page = nullptr;
}

CustomPopupPage::~CustomPopupPage()
{
}

void CustomPopupPage::setContentWidget(QWidget *page)
{
    if(!page)
        return;
    m_page = page;
    QVBoxLayout *layout = new QVBoxLayout(this);
    layout->setMargin(0);
    layout->addWidget(page);
}

QWidget *CustomPopupPage::getContentWidget()
{
    return m_page;
}

bool CustomPopupPage::event(QEvent *event)
{
    switch(event->type())
    {
    case QEvent::MouseButtonRelease:
    case QEvent::NonClientAreaMouseButtonRelease:
    {
        QMouseEvent *e=static_cast<QMouseEvent*>(event);
        if(e && e->button()==Qt::LeftButton)
        {
            emit signalDragRelease(e->globalPos());
        }
    }
        break;
    }
    return QDialog::event(event);
}

void CustomPopupPage::closeEvent(QCloseEvent *event)
{
    emit signalAddTab();
}

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值