Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Alp от Декабрь 21, 2009, 21:00



Название: Drag and Drop: удаление QDrag
Отправлено: Alp от Декабрь 21, 2009, 21:00
Есть следующая ситуация: сложный вложенный виджет (7 уровней вложенности), с одного из его детей начинается Drag. Вся обвеска для драг-дропа вынесена в отдельный класс QDraggableItem с конструктором принимающим виджет (для инициализации QDrag требуется виджет, с которого драг начался).
По завершению перетаскивания, в dropEvent'е происходит проверка стартового виджета и если с него был вытащен последний виджет стартовый удаляется.

И вот тут приложение падает поскольку владельцем QDrag'а был тот самый стартовый виджет. Если убираю удаление виджета QDrag успешно разрушается, но в непонятный момент. Создавать QDrag с родителем 0х0 (с целью самостоятельно разрушить, когда он уже не нужен) нельзя - драг не начнется. Удалять созданный драг руками так же не получается.

Вопрос: как эту ситуацию можно разрешить?


Название: Re: Drag and Drop: удаление QDrag
Отправлено: Igors от Декабрь 21, 2009, 21:30
Сам не решал но делал бы так: в деструкторе перекрытого QDrag испустил бы сигнал созданный с QueuedConnection (т.е. через очередь) а в слоте для этого сигнала уже спокойно удалял источник или что надо

Edit: и перекрывать не надо, есть удобный готовый сигнал destroyed


Название: Re: Drag and Drop: удаление QDrag
Отправлено: BRE от Декабрь 21, 2009, 23:08
Попробуй удалять с помощью deleteLater.


Название: Re: Drag and Drop: удаление QDrag
Отправлено: Alp от Декабрь 22, 2009, 01:13
Сам не решал но делал бы так: в деструкторе перекрытого QDrag испустил бы сигнал созданный с QueuedConnection (т.е. через очередь) а в слоте для этого сигнала уже спокойно удалял источник или что надо

Edit: и перекрывать не надо, есть удобный готовый сигнал destroyed
Спасибо, почитал про этот сигнал. Если я верно понял мысль, то мне надо вешаться на QDrag::destroyed, так? Увы, сделать не получится вот почему: обвязка для драга вынесена, как я писал в отдельный класс, который не наследует QObject и не декларирует Q_OBJECT, т.е. про сигналы-слоты он не знает ничего, но зато умеет создавать QDrag, запоминать точку начала перетаскивания и принимать или не принимать dragEnter.

Вот такая декларация:
Код
C++ (Qt)
class DraggableItem
{
   QWidget* widgetSelf;
 
   bool draggable;
   bool dragging;
   QPoint dragPos;
 
   QString     mimeType;
   QByteArray  mimeData;
 
protected:
   QPixmap dragpix;
   virtual void SetDragPixmap();
 
public:
   DraggableItem(QWidget* widgetSelf);
   virtual ~DraggableItem()    {}
 
   void SetDraggable(bool d)   { draggable = d; }
 
   bool Draggable()            { return draggable; }
 
   bool Dragging()             { return dragging; }
 
   QPoint DragPos()            { return dragPos; }
 
   void SetMimeData(const std::string& type, const QByteArray& data = QByteArray());
 
protected /*slots*/:
   virtual void mouseMoveEvent(QMouseEvent*);
   virtual void mousePressEvent(QMouseEvent*);
 
   virtual void dragEnterEvent(QDragEnterEvent*);
   virtual void dragLeaveEvent(QDragLeaveEvent*);
   virtual void dropEvent(QDropEvent*);
 
protected:
   virtual void StartDrag();
};
 

Т.е. имитация методов QWidget'а, реализующие базовую функциональность и перегружаемые в потомках.
На такое извращение пришлось пойти по той причине, что множественное наследование QObject не допускается, а делать линейное наследование просто глупо (например класс QEditLabel наследует: QBaseExtLabel(отсюда тянется QObject), EditableItem, DraggableItem, PairItem<QEditLabel>, в них заключена голая функциональность).

Привеситься на QDrag::destroyed с привязкой его к widgetSelf я не могу за отсутствием общего предка у удаляемых виджетов.


Название: Re: Drag and Drop: удаление QDrag
Отправлено: Alp от Декабрь 22, 2009, 01:15
Попробуй удалять с помощью deleteLater.
Не будет ли в этом случае UI отображать "как бы" удаленный виджет, который "пока не успел удалиться потому, что QDrag все еще жив"? Отсюда мой вопрос и проистекает - не удалось вяснить когда же именно происходит удаление QDrag'а его "источником".


Название: Re: Drag and Drop: удаление QDrag
Отправлено: BRE от Декабрь 22, 2009, 09:17
Не будет ли в этом случае UI отображать "как бы" удаленный виджет, который "пока не успел удалиться потому, что QDrag все еще жив"? Отсюда мой вопрос и проистекает - не удалось вяснить когда же именно происходит удаление QDrag'а его "источником".
Что значит не удалось выяснить? В документации все написано + есть исходники + можно проверить самому.  :)


Название: Re: Drag and Drop: удаление QDrag
Отправлено: Igors от Декабрь 22, 2009, 16:56
Спасибо, почитал про этот сигнал. Если я верно понял мысль, то мне надо вешаться на QDrag::destroyed, так? Увы, сделать не получится вот почему: обвязка для драга вынесена, как я писал в отдельный класс, который не наследует QObject и не декларирует Q_OBJECT, т.е. про сигналы-слоты он не знает ничего, но зато умеет создавать QDrag, запоминать точку начала перетаскивания и принимать или не принимать dragEnter.
...
Привеситься на QDrag::destroyed с привязкой его к widgetSelf я не могу за отсутствием общего предка у удаляемых виджетов.
Не проходят сигналы - не беда, никто не мешает Вам послать postEvent в деструкторе.