2014-10-20 69 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