這個功能看似簡單,實現起來確實有點兒難度。在代碼裡詳細說明吧。//CTabWidget.h#ifndef CTABWIDGET_H#define CTABWIDGET_H#include <QTabWidget>#include <QtGui>#include "CTabBar.h"class CTabWidget :public QTabWidget{ Q_OBJECTpublic: CTabWidget(QWidget* =0);virtual ~CTabWidget(){};public:CTabBar *tabBar;};#endif // CTABWIDGET_H//CTabWidget.cpp#include "CTabWidget.h"CTabWidget::CTabWidget(QWidget *parent):QTabWidget(parent){tabBar = new CTabBar;setTabBar(tabBar); //這裡是關鍵,這樣用我們自訂的CTabBar替換原來的QTabBar}//CTabBar.h#ifndef CTABBAR_H#define CTABBAR_H#include <QTabBar>#include <QtGui>class CTabBar :public QTabBar{Q_OBJECTpublic:CTabBar(QWidget* =0);virtual ~CTabBar(){};protected:void mousePressEvent(QMouseEvent *);void mouseReleaseEvent(QMouseEvent *); //通過兩個事件類比出tab被拖動的動作private:bool pressFlag;signals:void sig_tabDrag(int,QPoint);};#endif//CTabBar.cpp#include "CTabBar.h"#include <QtGui> CTabBar::CTabBar(QWidget *parent):QTabBar(parent),pressFlag(false){ } void CTabBar::mousePressEvent(QMouseEvent *event){ if (event->button()==Qt::LeftButton) { pressFlag = true; } QTabBar::mousePressEvent(event);} void CTabBar::mouseReleaseEvent(QMouseEvent *event){ if(event->button() == Qt::LeftButton &&pressFlag ) { pressFlag = false; if(tabRect(currentIndex()).contains( event->pos())) return; emit sig_tabDrag(currentIndex(),event->pos()); } }現在實現視窗標題列被雙擊動作//CWidget.h#ifndef CWIDGET_H#define CWIDGET_H#include <QtGui/QWidget>class CWidget:public QWidget{Q_OBJECTpublic:CWidget(QWidget* = 0);~CWidget();protected:bool event(QEvent *);signals:void sig_doubleClickedTitleBar(); //被雙擊時發射的訊號};#endif//CWidget.cpp#include "CWidget.h"#include <QtGui>CWidget::CWidget(QWidget *parent):QWidget(parent){}CWidget::~CWidget(){}bool CWidget::event(QEvent *event){#ifdef unix if(event->type() == QEvent::MouseButtonDblClick){ //標題列單擊沒反應,就單擊視窗邊緣替代吧 emit sig_doubleClickedTitleBar(); return true; }#endif if (event->type() == QEvent::NonClientAreaMouseButtonDblClick) //這個事件在Linux下沒有觸發,應該算是Qt的一個Bug吧 {emit sig_doubleClickedTitleBar();return true;} return QWidget::event(event);}//CMainWindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#include <QTextEdit>#include "CTabWidget.h"#include "CTabBar.h"class CMainWindow:public QMainWindow{Q_OBJECTpublic:CMainWindow(QWidget* = 0); private:CTabWidget *tabWidget;private slots: void slot_tabBarDoubleClicked(); //響應雙擊彈回的槽函數 void slot_tabDrag(int index,QPoint point); //響應拖動動作的槽函數 void slot_closeTab(int); //關閉tab的槽函數};#endif // MAINWINDOW_H//CMainWindow.cpp#include "CMainWindow.h"#include "CTabWidget.h"#include "CWidget.h"#include <QtGui>CMainWindow::CMainWindow(QWidget *parent):QMainWindow(parent){ tabWidget = new CTabWidget(this); tabWidget->setMovable(true); tabWidget->setTabsClosable(true); tabWidget->setTabShape(QTabWidget::Triangular); //添加4個tab頁 tabWidget->addTab(new QTextEdit,"eidt 1"); tabWidget->addTab(new QTextEdit,"eidt 2"); tabWidget->addTab(new QTextEdit,"eidt 3"); tabWidget->addTab(new QTextEdit,"eidt 4"); setCentralWidget(tabWidget); connect(tabWidget->tabBar,SIGNAL(sig_tabDrag(int,QPoint)),this,SLOT(slot_tabDrag(int,QPoint))); connect(tabWidget,SIGNAL(tabCloseRequested(int)),this,SLOT(slot_closeTab(int))); connect(tabWidget,SIGNAL(currentChanged(int)),tabWidget,SLOT(setCurrentIndex(int))); resize(800,600);}void CMainWindow::slot_tabDrag(int index,QPoint point){ CWidget *widget = new CWidget; QWidget *draged = tabWidget->widget(index); QString windowName = tabWidget->tabText(index); tabWidget->removeTab(index); connect(widget,SIGNAL(sig_doubleClickedTitleBar()),this,SLOT(slot_tabBarDoubleClicked())); QGridLayout *layout = new QGridLayout; layout->addWidget(draged); widget->setLayout(layout); widget->resize(600,400); widget->move(point+pos()+tabWidget->pos()); widget->setWindowTitle(windowName); widget->show(); draged->show();}void CMainWindow::slot_tabBarDoubleClicked(){ CWidget *widget = qobject_cast<CWidget*>(sender()); QObjectList list = widget->children(); QTextEdit *edit = NULL; for(int i = 0;i<list.count();++i) { if(list[i]->inherits("QTextEdit")) { edit = qobject_cast<QTextEdit*>(list[i]); break; } } if(edit == NULL) { return ; } edit->setParent(tabWidget); tabWidget->addTab(edit,widget->windowTitle()); delete widget;}void CMainWindow::slot_closeTab(int index){ QWidget *draged = tabWidget->widget(index); tabWidget->removeTab(index); delete draged;}//main.cpp#include "CMainWindow.h"#include <QApplication>#include <QCleanlooksStyle>int main(int argc,char **argv){ QApplication app(argc,argv); QApplication::setStyle(new QCleanlooksStyle); QTextCodec::setCodecForTr(QTextCodec::codecForName("gb2312")); CMainWindow mainwindow;mainwindow.show(); return app.exec();}