首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 移动开发 > QT开发 >

在Qt中怎样才能兑现实现类似与360浏览器的标签页拖拽功能,在拖拽时产生一个新窗口

2012-12-15 
在Qt中怎样才能实现实现类似与360浏览器的标签页拖拽功能,在拖拽时产生一个新窗口?各位走过的路过的大哥:

在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的索引值

引用:
补充一下,一定要点击便签位置,拖拽,显示截图,松开鼠标产生新窗口,包括父窗口之外,桌面。

[解决办法]
//处理currentChanged 的槽函数
void Widget::handleTabPress(int index)
{
  qDebug("current index:%d",index);
  QWidget *child = tabwidget->widget(index);
}
要不要 构造 Drag对象,再实现drop?

new拖动对象A(A要重写mousMoveEvent事件)?这个我还不太理解


[解决办法]
ao834391367
 
QQ多少?可以详细聊一聊。
879768685
[解决办法]
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{

  ui->setupUi(this);

  tabwidget =  new MyTabWidget;
  tabwidget->addTab(new QLabel("page 0"),QIcon(),"page_0");
  tabwidget->addTab(new QLabel("page 1"),QIcon(),"page_1");
  tabwidget->addTab(new QLabel("page 2"),QIcon(),"page_2");
  tabwidget->setMovable(true);

  connect(tabwidget,SIGNAL(currentChanged(int)),
          this,SLOT(handleTabPress(int)));
  QHBoxLayout * ly = new QHBoxLayout;
  ly->addWidget(tabwidget);
  setLayout(ly);

    setAcceptDrops(true);
//    setAttribute(Qt::WA_TransparentForMouseEvents);


}
void Widget::handleTabPress(int index)
{
  qDebug("current index:%d",index);
       QWidget *child = tabwidget->widget(currPageIndex);
       if (!child)
           return;

       QByteArray itemData;
       QDataStream dataStream(&itemData, QIODevice::WriteOnly);
       dataStream << (int32_t)child << index;

       QMimeData *mimeData = new QMimeData;
       mimeData->setData("application/x-fridgemagnet", itemData);
       //mimeData->setText(child->labelText());

       QDrag *drag = new QDrag(this);
       drag->setMimeData(mimeData);
       QPixmap p = QPixmap::grabWindow(child->winId(),0,0,child->width(),child->height());
       drag->setPixmap(p);
       //drag->setDragCursor(QPixmap(":/cursor.png"),Qt::CopyAction);

       if (drag->exec(Qt::MoveAction 


[解决办法]
 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
请问是什么原因啊???

热点排行