2014-10-20 66 views
2

我正在实现drap-and-drop事件过滤器来重新排列布局中的小部件,并且一次将其中几个弹出到队列中,在拖动小部件所在的位置添加橡皮筋,然后添加小部件的其余部分回布局(因为似乎没有被使用QLayout接口“在插入”的方式)像这样:任何方式来暂时停止布局重新计算?

// HANDLE DRAG ENTER EVENTS 
if (p_event->type() == QEvent::DragEnter) 
{ 
    QDragEnterEvent* dragEnterEvent = static_cast<QDragEnterEvent*>(p_event); 
    if (dragEnterEvent->mimeData()->hasFormat("text/plain")) 
    { 
     QString objectName = dragEnterEvent->mimeData()->text(); 

     // findChild doesn't work on layouts because they don't ever 
     // inject themselves into the parent/child hierarchy, so we 
     // use the itemAt approach instead. 
     for (int i = 0; i < layout->count(); ++i) 
     { 
      dragItem = layout->itemAt(i)->widget(); 
      if (dragItem->objectName() == objectName) 
      { 
       dragEnterEvent->acceptProposedAction(); 

       // 'Rearrange' the widgets. This basically entails removing 
       // everything after the drag item, adding a placeh older, and 
       // then adding them back 
       QQueue<QWidget*> fifo; 

       // take everything after the drag item out 
       // important to have count as a local var, because otherwise it will 
       // decrement with every loop iteration. 
       int count = layout->count();       
       for (int j = i + 1; j < count; j++) 
       { 
        fifo.enqueue(layout->takeAt(i+1)->widget());  // the indices shift left on their own, so we only ever want to take i+1.       
       } 

       // add a 'rubber band' placeholder 
       m_band = new QRubberBand(QRubberBand::Rectangle); 
       m_band->setObjectName("placeholderBand"); 
       m_band->setVisible(true); 
       m_band->setFixedSize(dragItem->size()); 
       layout->addWidget(m_band);    

       // put the widgets in the fifo back in 
       count = fifo.count(); 
       for(int j = 0; j < count; j++) 
       { 
        layout->addWidget(fifo.dequeue()); 
       } 

       break; 
      } 
     } 
    }    
} 

这种方法的问题是加法/小部件的去除导致非常明显和令人讨厌的闪烁。是否有任何

  1. 一些方法可以让我从重新计算本身直到所有的添加/删除操作停止布局完成后,或
  2. 一些更好的方式来插入部件到布局(仅使用QLayout接口)那不会造成闪烁?
+0

是的,你说得对,我看到更多的源和内addWidget只有 'addChildWidget(W);' '的addItem( QLayoutPrivate :: createWidgetItem(this,w));'并且没有任何一种方法不会调用update或其他东西 – Chernobyl 2014-10-20 19:15:11

回答

0

不确定它会有帮助,因为我用在不同的上下文中(语义语法突出显示,在我的项目loqt)。

#ifndef BLOCKSIG_H 
#define BLOCKSIG_H 

#include <QObject> 
#include <QPointer> 

/** temporary stop signals communication 
* use with care: notably QTextEdit formatting can be lost 
* on multiple changes notification 
*/ 
struct blockSig { 

    blockSig(QObject* target) : target(target) { current = target->blockSignals(true); } 
    ~blockSig() { off(); } 

    void off() { if (target) { target->blockSignals(current); target = 0; } } 

private: 

    QPointer<QObject> target; 
    bool current; 
}; 

#endif 

例如使用,避免对格式不必要的通知改变

#include "blockSig.h" 

void ConsoleEdit::selectionChanged() 
{ 
    blockSig bs(this); 

    foreach (ExtraSelection s, extraSelections()) 
     s.cursor.setCharFormat(s.format); 
    extraSelections().clear(); 

    ... 
} 
+0

感谢您的建议。没有为这个特殊问题工作,但这是一个有用的想法。 – 2014-10-21 14:05:07