QTabWidget 实现类似QQ聊天窗口

        新版本的QQ聊天窗口可以实现拖动,分离出新的窗口。浏览器等软件也可以实现类似操作。所以心血来潮想用Qt实现类似的功能。想用QTabWidget直接实现是很难的,仔细阅读源码,发现QTabWidget内部是由QStackedWidget和QTabBar组合实现的。所以很自然的想到,只要继承QTabBar的子类重新实现QTabBar的
void mousePressEvent (QMouseEvent *e);
void mouseMoveEvent (QMouseEvent *e);
void mouseReleaseEvent (QMouseEvent *e);

这三个方法,再把子定义的TabBar设置给QTabWidget就差不多了。但是还有个问题,QTabWidget的 setTabBar方法是protected的,所以只好再自定义一个QTabWidget的子类,在子类里调用setTabBar了。以下是我的简单实现:

class myTabBar:public QTabBar
{
	Q_OBJECT
public:
	myTabBar(QWidget *parent = NULL);
	~myTabBar();
protected:
	void mousePressEvent (QMouseEvent *e);
	void mouseMoveEvent (QMouseEvent *e);
	void mouseReleaseEvent (QMouseEvent *e);

 signals:
	void starDragTab(int index);
	void endDragTab();
private:
	void drag();

	bool      m_isDrag;
	QPoint    m_mousePressPoint;
	QPoint    m_mouseReleasePoint;
	
};

void myTabBar::mouseMoveEvent(QMouseEvent *e)
{
	int index = this->currentIndex();
	
	if (m_isDrag)
	{
		QPoint Point = e->pos();
                //拖动的垂直距离大于Bar的高度的话就新建一个窗口,这个应该比较好理解啊
		if (qAbs(m_mousePressPoint.y() - Point.y()) > this->height())
		{
			emit starDragTab(index);
		}
	}
	QTabBar::mouseMoveEvent(e);
}

void myTabBar::mousePressEvent(QMouseEvent *e)
{
	if (e->button() == Qt::LeftButton)
	{
		m_isDrag = true;
		m_mousePressPoint = e->pos();
	}
	QTabBar::mousePressEvent(e);
}

void myTabBar::mouseReleaseEvent(QMouseEvent *e)
{
	if (e->button() == Qt::LeftButton)
	{
		m_mouseReleasePoint = e->pos();
		if (qAbs(m_mousePressPoint.y() - m_mouseReleasePoint.y()) > this->height())
		{
			emit endDragTab();
		}
	}
	QTabBar::mouseReleaseEvent(e);
}

class myTabWidget:public QTabWidget
{
	Q_OBJECT

public:
	myTabWidget(QWidget *parent = NULL);

	~myTabWidget();


private slots:
	void starDrag(int index);
	void endDrag();
	
private:
	myTabBar      *m_pTabBar;
	QString        m_dragTabLabel;
	QWidget       *m_pDragWidget;
	int            m_dragIndex;
	
	
};

myTabWidget::myTabWidget(QWidget *parent/* = NULL*/):QTabWidget(parent)
{
	this->setAcceptDrops(true);
	setMouseTracking(true);
	m_pTabBar = new myTabBar(this);
	m_pTabBar->setMovable(true);
	setTabBar(m_pTabBar);               //设置自定义的Bar给TabWidget
	m_pDragWidget = NULL;
	connect(m_pTabBar,SIGNAL(starDragTab(int)),this,SLOT(starDrag(int)));
	connect(m_pTabBar,SIGNAL(endDragTab()),this,SLOT(endDrag()));
}

void myTabWidget::starDrag(int index)
{
	m_dragTabLabel = this->tabText(index);
	m_pDragWidget  = this->widget(index);
	m_dragIndex    = index;
	QPixmap pix;
	//pix = QPixmap::grabWidget(m_pDragWidget);
	pix = QPixmap::grabWindow(this->winId());
	if (pix.isNull())
	{
		int i;
	}
	QMimeData *mimeData = new QMimeData;
	//mimeData->setText("drag tab");
	QDrag *drag = new QDrag(this);
	drag->setMimeData(mimeData);
	drag->setPixmap(pix.scaled(QSize(200,200)));    //这里主要是想想QQ一样,可以拖动的过程显示被拖动窗口的图片。但是效果还不是很好
	drag->exec();
}

void myTabWidget::endDrag()
{
	myTabWidget *pWidget = new myTabWidget(NULL);
	if (m_pDragWidget)
	{
                 //新建一个独立的窗口
		removeTab(m_dragIndex);
		pWidget->addTab(m_pDragWidget,m_dragTabLabel);
		pWidget->show();
	}
	
}




你可能感兴趣的:(qt)