Russian Qt Forum
Ноябрь 25, 2024, 20:29 *
Добро пожаловать, Гость. Пожалуйста, войдите или зарегистрируйтесь.
Вам не пришло письмо с кодом активации?

Войти
 
  Начало   Форум  WIKI (Вики)FAQ Помощь Поиск Войти Регистрация  

Страниц: [1]   Вниз
  Печать  
Автор Тема: Drag and Drop  (Прочитано 7063 раз)
gueRRero
Гость
« : Май 04, 2009, 20:52 »

Сразу прошу прощение за название, не отражающее сущности вопроса (другого не придумал))) и за размеры вопроса (с лаконичностью у меня так же плохо, как и с фантазией).
Итак, проблема следующая:
Нужно было наладить drag and drop между двумя списками. Для этого я написал класс, унаследованный от QListWidget (своего, собственно, ничего не придумал, а подсмотрел в книжке Жасмин Бланшет "Qt4: Программирование GUI на C++"):
Код
C++ (Qt)
List.h
 
#ifndef LIST_H
#define LIST_H
 
#include <QListWidget>
 
class List : public QListWidget
{
Q_OBJECT
 
public:
List(QWidget *prnt = 0);
 
protected:
void mousePressEvent(QMouseEvent *event);
void mouseMoveEvent(QMouseEvent *event);
void dragEnterEvent(QDragEnterEvent *event);
void dragMoveEvent(QDragMoveEvent *event);
void dropEvent(QDropEvent *event);
 
private:
void startDrag();
QPoint startPos;
};
 
#endif //LIST_H

Код
C++ (Qt)
List.cpp
 
#include "List.h"
 
#include <QtGui/QApplication>
#include <QMouseEvent>
 
//--------------------------------------------------------------------------------------
 
List::List(QWidget *prnt /* = 0 */): QListWidget(prnt)
{
 
setSelectionMode(QAbstractItemView::SingleSelection);
setDragEnabled(true);
viewport()->setAcceptDrops(true);
setDropIndicatorShown(true);
 
}
 
//--------------------------------------------------------------------------------------
//---------------------------------Events-----------------------------------------------
//--------------------------------------------------------------------------------------
 
void List::mousePressEvent(QMouseEvent *event)
{
if(event->button() == Qt::LeftButton)
startPos=event->pos();
QListWidget::mousePressEvent(event);
}
 
//--------------------------------------------------------------------------------------
 
void List::mouseMoveEvent(QMouseEvent *event)
{
if(event->buttons() & Qt::LeftButton)
{
int distance = (event->pos() - startPos).manhattanLength();
if(distance >= QApplication::startDragDistance())
startDrag();
}
QListWidget::mouseMoveEvent(event);
}
 
//--------------------------------------------------------------------------------------
 
void List::dragEnterEvent(QDragEnterEvent *event)
{
List* source = qobject_cast<List *>(event->source());
if(source && source != this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
}
 
//--------------------------------------------------------------------------------------
 
void List::dragMoveEvent(QDragMoveEvent *event)
{
List* source = qobject_cast<List *>(event->source());
if(source && source != this)
{
event->setDropAction(Qt::MoveAction);
event->accept();
}
}
 
//--------------------------------------------------------------------------------------
 
void List::dropEvent(QDropEvent *event)
{
List* source = qobject_cast<List *>(event->source());
if(source && source != this)
{
addItem(event->mimeData()->text());
event->setDropAction(Qt::MoveAction);
event->accept();
}
}
 
//--------------------------------------------------------------------------------------
//----------------------------------Functions-------------------------------------------
//--------------------------------------------------------------------------------------
 
void List::startDrag()
{
QListWidgetItem*  _item = currentItem();
if(_item)
{
QMimeData* mimeData = new QMimeData;
mimeData->setText(_item->text());
QDrag* drag = new QDrag(this);
drag->setMimeData(mimeData);
if(drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete _item;
}
 
}

Все нормально работает, но меня смущает следующее место:
Код
C++ (Qt)
void List::startDrag()
{
QListWidgetItem*  _item = currentItem();
if(_item)
{
QMimeData* mimeData = new QMimeData;
mimeData->setText(_item->text());
QDrag* drag = new QDrag(this);
drag->setMimeData(mimeData);
if(drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete _item;
}
 
}

mimeData и drag создаются, но нигде не удаляются. Не будет ли утечки памяти? Или я ошибаюсь, и они все-таки где-то удаляются?

З.Ы.: Попытка сделать их auto_ptr не удалась:
Код
C++ (Qt)
//List.h
.....
   std::auto_ptr<QMimeData> mimeData;
   std::auto_ptr<QDrag> drag;
.....
 
//List.cpp
......
void List::startDrag()
{
QListWidgetItem*  _item = currentItem();
if(_item)
{
mimeData.reset(new QMimeData);
mimeData->setText(_item->text());
drag.reset(new QDrag(this));
drag->setMimeData(mimeData.get());
if(drag->exec(Qt::MoveAction) == Qt::MoveAction)
delete _item;
}
 
}
Данная функция нормально срабатывает один раз, но на второй - падает на mimeData.reset(new QMimeData). Буду благодарен, если кто-нибудь объяснит, почему это происходит.
« Последнее редактирование: Май 04, 2009, 20:59 от guajiro » Записан
Rcus
Гость
« Ответ #1 : Май 04, 2009, 21:10 »

Assistant -> Drag and Drop:
Цитировать
Drag and Drop Actions

In the simplest case, the target of a drag and drop action receives a copy of the data being dragged, and the source decides whether to delete the original. This is described by the CopyAction action. The target may also choose to handle other actions, specifically the MoveAction and LinkAction actions. If the source calls QDrag::exec(), and it returns MoveAction, the source is responsible for deleting any original data if it chooses to do so. The QMimeData and QDrag objects created by the source widget should not be deleted - they will be destroyed by Qt. The target is responsible for taking ownership of the data sent in the drag and drop operation; this is usually done by keeping references to the data.
Записан
gueRRero
Гость
« Ответ #2 : Май 04, 2009, 21:18 »

Спасибо огромное. Везет же тем, кто знает английский. Понял не все, но главное, что they will be destroyed by Qt. Кстати, нету ли где-нибудь случайно Assistant на русском?
Записан
spirit
Гость
« Ответ #3 : Май 04, 2009, 21:20 »

http://www.doc.crossplatform.ru/qt/4.5.0/
Записан
pastor
Administrator
Джедай : наставник для всех
*****
Offline Offline

Сообщений: 2901



Просмотр профиля WWW
« Ответ #4 : Май 04, 2009, 21:21 »

Кстати, нету ли где-нибудь случайно Assistant на русском?

В этом же разделе несколькими темами выше -  документация по Qt4 на русском )))
Записан

Integrated Computer Solutions, Inc. (ICS)
http://www.ics.com/
gueRRero
Гость
« Ответ #5 : Май 04, 2009, 21:23 »

Пардон, туплю)))))
Записан
ритт
Гость
« Ответ #6 : Май 05, 2009, 00:33 »

а давайте создадим прямо отдельный раздел "документация по Qt на русском" и закрепим там соответствующую ветку? /* и там же ещё можно было бы закрепить "как пользоваться поиском" Улыбающийся */
Записан
gueRRero
Гость
« Ответ #7 : Май 06, 2009, 19:12 »

В продолжение вопроса (Извините, если опять спрашиваю глупости). Могут ли функции setMimeData и exec бросить исключение, если могут, то что при этом будет с указателем?
В исходниках (qt/src/gui/kernel/gdrag.cpp) я исключений не увидел, но хотелось бы уточнить у специалистов (вдруг я не туда смотрел).
Записан
gueRRero
Гость
« Ответ #8 : Май 06, 2009, 21:00 »

И еще. Вот только что обнаружил:
При перетаскивании, когда кнопку мыши отпускаешь, при этом мышь не двигая (совсем, чтоб даже не дрогнула), перетаскиваемый объект остается возле указателя мыши. Только когда мышку чуть шевельнешь, тогда только объект отпускается на нужное место.  Иногда все нормально, иногда так вот странно...
Это наблюдается и при использовании ранее приведенного кода и при использовании стандартных QListWidget, QTreeWidget.
Никто с таким не сталкивался? В чем может быть проблема? Как с ней бороться?
Записан
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


Страница сгенерирована за 0.175 секунд. Запросов: 23.