目录
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_HCustomTabBar
#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(); }