在Qt中怎样才能实现实现类似与360浏览器的标签页拖拽功能,在拖拽时产生一个新窗口?
各位走过的路过的大哥:
小弟已经为此问题纠结了N久,并可能仍将纠结下去,直到有贵人相助。最近小弟接到一个任务。
1、用QTabWidget做页面切换。
2、通过拖拽标签产生新窗口,并在拖拽时显示该窗口的截图。
3、新窗口产生后,原有标签从QTabWidget删除。
4、在拖拽后并且未drop时,放弃拖拽,便签仍可恢复到原位置正常显示。
5、即使拖拽到应用程序主窗体之外(桌面),也可实现drop结果。
6、拖拽标签,左右移动,当便签位于另一个便签上方时,该标签自动切换位置。效果和QTabwidget的setMovable()一直。
目前小弟的问题主要在于,1、不知道QTabWidget的拖拽实现怎么实现,2、如何获取QTabWidget标签的对象。
3、在窗体之外如何能相应dropEvenet事件。
以上效果,在某公司做的Qt程序中均有实现,或许不是QTabWidget实现,可否提供思路,避免小弟再撞南墙。高分重谢!!
[解决办法]
该回复于2012-09-17 10:40:38被版主删除
[解决办法]
哈。 这个挺有意思的。应该能实现。等下试试看。
[解决办法]
期待中....
[解决办法]
Qt 有个自带的浏览器的demo程序,很不错,你可以下载下来看看。
[解决办法]
楼上的提供的回答,我去看了,Qt浏览器的view时用tabWidget实现的,仅仅是可以移动标签。但并未实现拖拽标签产生窗口的功能。
[解决办法]
LZ应该纠结的是拖动的过程吧 可以拖动的时候,可以new一个对象A,给他贴上截图的图片,重写A的鼠标mousemoveEvent事件(鼠标移动时,不断更新A的位置,实现鼠标拖动的效果);1.拖拽的代码要自己实现的
2.void QTabWidget::currentChanged ( int index ) [signal] 这个可以得到当前的活动tab 3.也是要写代码实现的呵呵
[解决办法]
1、我试着重载tabWidget所在窗口的mousePressEvent事件,当点击QTabwidget的窗体部分,press事件有响应,但点击标签位置走不到mousePressEvent,接下来的点击标签的QDrag对象在哪里new??
2.子类化QTabWidget,重载mousePressEvent,现象和上面的情况一样。
3、通过connect(tabwidget,SIGNAL(currentChanged(int)),this,SLOT(getCurrTabPage(int)));
获得当前标签对应的Widget指针,这又有什么用呢,关键是在什么地方构造drag对象!!
感谢楼上的热心回答
[解决办法]
哈。昨天没时间。 今天上午做了点小的实验。 貌似用eventfilter就可以了。不用重载那么麻烦( = =,其其实重载貌似也不麻烦。)。 毕竟主要是获得鼠标事件。
其实这个可以跟drag没啥关系。直接用mouseEvent来实现。
之前我纠结的是拖到外面需要开启个新进程么?
后面发现直接用QDialog作为容器就可以了。
下面的代码会有内存泄漏。到时候写成类成员标量就可以。是拖出需要新建的tab
//创建容器
QWidget *window = new QDialog();
QTabWidget *tempTabWidget = new QTabWidget(window);
tempTabWidget->setGeometry(0,0,400,300);
//把tab移动到新容器
QWidget *currentWidget = ui->tabWidget->currentWidget();
currentWidget->setParent(0);
tempTabWidget->addTab(currentWidget ,"cuicui");
window->show();
当然在mousePressEvent, mouseReleaseEvent(), mouseMove..里面做一些判断来表示
拖动tab的时候需要创建新的一个。还是需要回到原来的位置。
关于拖动时的效果
一样创建一个Dialog设置成半透明效果,然后把currentWidget render成图片画到Dialog上。哈哈。
mouseMove的时候这个Dialog跟着走就好了。
问题应该不大。嘎嘎。。
[解决办法]
QDockWidget
[解决办法]
问一句,mousePressEvent, mouseReleaseEvent(), mouseMove..在哪个类中实现?
eventfileter 过滤哪个对象,如果是tabwidget的话,导致我点击tabwidget的除了便签之外的任何位置将会产生响应,事实上相反,mousepressEvent在点击标签的时候没有反应。
另外,用QDockWidget实现的效果和我想要的相差很大,可能不能采用。
------解决方案--------------------
补充一下,一定要点击便签位置,拖拽,显示截图,松开鼠标产生新窗口,包括父窗口之外,桌面。
[解决办法]
过程是这样的:点击标签,new拖动对象A(A要重写mousMoveEvent事件),tabwidge移除点击的tabB,鼠标移动的话A随鼠标移动,要是A在tabwidget的范围外就在new一个tabwidget加上去tabB,要是在tabwidget的范围内就在再加上tabB,tabwidget的mouseMoveEvent不用重写;
void QTabWidget::currentChanged ( int index ) [signal]这个信号是tabwidget上的tab页发生变化时发出的,实现拖动改变顺序写个槽函数连起来实现就可以了 int index就是发生改变tab的索引值
[解决办法]
Qt::CopyAction, Qt::CopyAction) == Qt::MoveAction)
// child->close();
// else
// child->show();
{
}
}
void Widget::mouseReleaseEvent(QMouseEvent *event)
{
}
Widget::~Widget()
{
delete ui;
}
void Widget::changeEvent(QEvent *e)
{
QWidget::changeEvent(e);
switch (e->type()) {
case QEvent::LanguageChange:
ui->retranslateUi(this);
break;
default:
break;
}
}
void Widget::dragEnterEvent(QDragEnterEvent *event)
{
if (event->mimeData()->hasFormat("application/x-fridgemagnet")) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void Widget::dragMoveEvent(QDragMoveEvent *event)
{
if (event->mimeData()->hasFormat("application/x-fridgemagnet")) {
if (children().contains(event->source())) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
void Widget::dropEvent(QDropEvent *event)
{
if (event->mimeData()->hasFormat("application/x-fridgemagnet")) {
const QMimeData *mime = event->mimeData();
QByteArray itemData = mime->data("application/x-fridgemagnet");
QDataStream dataStream(&itemData, QIODevice::ReadOnly);
QWidget * tabPage;
int32_t int_addr_ptr;
int currentIndex;
dataStream >> int_addr_ptr >> currentIndex;
tabPage = (QWidget*)int_addr_ptr;
tabwidget->removeTab(currentIndex);
QTabWidget *newTabWidget = new QTabWidget;;
newTabWidget->addTab(tabPage,QIcon(),"new");
newTabWidget->show();
newTabWidget->setAttribute(Qt::WA_DeleteOnClose);
if (event->source() == this) {
event->setDropAction(Qt::MoveAction);
event->accept();
} else {
event->acceptProposedAction();
}
} else if (event->mimeData()->hasText()) {
event->acceptProposedAction();
} else {
event->ignore();
}
}
drop时,内存出错
info:
current index:1
current index:1
current index:0
current index:-1
ASSERT failure in QList<T>::operator[]: "index out of range", file ..\..\include/QtCore/../../src/corelib/tools/qlist.h, line 447
C:\Documents and Settings\Administrator\My Documents\1_btnmove\debug\btnmove.exe
exited with code 3
请问是什么原因啊???