QTabWidget 实现类似QQ聊天窗口(拖动分离出新的窗口)
2016-02-01 18:17
971 查看
新版本的QQ聊天窗口可以实现拖动,分离出新的窗口。浏览器等软件也可以实现类似操作。所以心血来潮想用Qt实现类似的功能。想用QTabWidget直接实现是很难的,仔细阅读源码,发现QTabWidget内部是由QStackedWidget和QTabBar组合实现的。所以很自然的想到,只要继承QTabBar的子类重新实现QTabBar的
[cpp] view plain copy
void mousePressEvent (QMouseEvent *e);
void mouseMoveEvent (QMouseEvent *e);
void mouseReleaseEvent (QMouseEvent *e);
这三个方法,再把子定义的TabBar设置给QTabWidget就差不多了。但是还有个问题,QTabWidget的 setTabBar方法是protected的,所以只好再自定义一个QTabWidget的子类,在子类里调用setTabBar了。以下是我的简单实现:
[cpp] view plain copy
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;
};
[cpp] view plain copy
void myTabBar::mouseMoveEvent(QMouseEvent *e)
{
int index = this->currentIndex();
if (m_isDrag)
{
QPoint Point = e->pos();
[cpp] view plain copy
//拖动的垂直距离大于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);
}
[cpp] view plain copy
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;
};
[cpp] view plain copy
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)
{
[cpp] view plain copy
//新建一个独立的窗口
removeTab(m_dragIndex);
pWidget->addTab(m_pDragWidget,m_dragTabLabel);
pWidget->show();
}
http://blog.csdn.net/hai200501019/article/details/8987379
[cpp] view plain copy
void mousePressEvent (QMouseEvent *e);
void mouseMoveEvent (QMouseEvent *e);
void mouseReleaseEvent (QMouseEvent *e);
这三个方法,再把子定义的TabBar设置给QTabWidget就差不多了。但是还有个问题,QTabWidget的 setTabBar方法是protected的,所以只好再自定义一个QTabWidget的子类,在子类里调用setTabBar了。以下是我的简单实现:
[cpp] view plain copy
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;
};
[cpp] view plain copy
void myTabBar::mouseMoveEvent(QMouseEvent *e)
{
int index = this->currentIndex();
if (m_isDrag)
{
QPoint Point = e->pos();
[cpp] view plain copy
//拖动的垂直距离大于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);
}
[cpp] view plain copy
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;
};
[cpp] view plain copy
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)
{
[cpp] view plain copy
//新建一个独立的窗口
removeTab(m_dragIndex);
pWidget->addTab(m_pDragWidget,m_dragTabLabel);
pWidget->show();
}
http://blog.csdn.net/hai200501019/article/details/8987379
相关文章推荐
- Qt 状态机框架学习(没学会)
- Qt 智能指针学习(7种QT智能指针和4种std智能指针)
- qt 使用xlslib操作execl
- 使用Qt库时出现winsock2.h和windos.h包含顺序错误
- PyQt5 笔记(04):主窗口卡死问题
- Ogre3D嵌入Qt框架 之 小结
- 分享一个自己写的QT小游戏-玛丽奥医生
- Qt 学习之路 2(31):贪吃蛇游戏(1)
- 使用Qt开发俄罗斯方块游戏(1)
- QTableWidget 导出到表格
- QT5的软键盘输入法实现
- QT一些基本的操作(文件、图片等)
- QT5的软键盘输入法实现
- PyQt5 笔记(03):弹出窗口大全
- 使用 Qt InstallFramework 进行程序打包(一)
- PyQt5 笔记(02):嵌套布局
- PyQt5 笔记(01):嵌套布局
- QT 实现在一个模块中间显示一个红色提示框,3秒后消失
- QT中实现程序只运行一个实例--应用程序的单例化
- Qt VTK QVTK.dll