Есть ли способ временно остановить перерасчет макета?
Я реализую фильтр событий 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;
}
}
}
}
Проблема с этим подходом состоит в том, что добавление / удаление виджетов вызывает очень заметное и неприятное мерцание. Есть ли
- каким-то образом я могу остановить повторный расчет макета до тех пор, пока не будут выполнены все операции добавления / удаления, или
- лучший способ вставить виджеты в макет (используя только
QLayout
интерфейс), который не вызовет мерцания?
1 ответ
Не уверен, что это поможет, так как я использовал в другом контексте (подсветка семантического синтаксиса, в моем проекте 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();
...
}