Qt实现窗口tabwidget的拖出双击弹回功能

这个功能看似简单,实现起来确实有点儿难度。
在代码里详细说明吧。
//CTabWidget.h
#ifndef CTABWIDGET_H
#define CTABWIDGET_H
#include <QTabWidget>
#include <QtGui>
#include "CTabBar.h"

class CTabWidget :public QTabWidget
{
    Q_OBJECT
public:
    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_OBJECT
public:
	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_OBJECT
public:
	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_OBJECT
public:
	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();
}




评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值