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

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

Страниц: [1]   Вниз
  Печать  
Автор Тема: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую  (Прочитано 4784 раз)
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« : Июнь 23, 2011, 17:47 »

Это очень частая потребность, надо практически в любом приложении, где что-либо рисуется на графической сцене. Сцена может быть одна или несколько, не суть важно. Предлагают в таком случае наследовать QMimieData, но это муторно, когда нужно просто передать указатель. Поисследовав тему, не найдя готового примера, пришел к такому коду:

В классе, ConnectableItem : QGraphicsItem появился такой метод:

Код:
    virtual void mouseMoveEvent(QGraphicsSceneMouseEvent *event)
    {
        if( QLineF(event->screenPos(), event->buttonDownScreenPos(Qt::LeftButton)).length()
            < QApplication::startDragDistance())
            return;
        QDrag* drag = new QDrag( event->widget() );
        QMimeData *mimeptr = new QMimeData();
        ConnectableItem *_this = this;
        QByteArray data;
        QDataStream stream( &data, QIODevice::WriteOnly );
        stream.writeRawData( (const char*) &_this, sizeof( _this ) );
        mimeptr->setData( ITEMDRAGMIMETYPE, data ); // ITEMDRAGMIMETYPE это #define-d псевдо-майм-тип
        drag->setMimeData( mimeptr );
        drag->setPixmap( QPixmap( pic ) ); // pic это указатель на строку с именем картинки в ресурсах приложения
        drag->exec();
    }

а в классе сцены, который наследует QGraphicsScene, приемник бросаний реализован так:

Код:
void DragDropScene::dropEvent( QGraphicsSceneDragDropEvent *event )
{
    ConnectableItem* item;
    QByteArray data = event->mimeData()->data( ITEMDRAGMIMETYPE );
    QDataStream stream( &data, QIODevice::ReadOnly );
    stream.readRawData( (char*) &item, sizeof( item ) );
    item->setPos( event->scenePos() );
    addItem( item );
    update();
}

и все работает...

ЗЫ: если кто будет тупо повторять, имейте в виду, что для того, чтобы вообще заработало, надо в наследнике QGraphicsScene реализовать оба метода dragEnterEvent и dragMoveEvent, как минимум, так:

Код:
void DragDropScene::dragEnterEvent( QGraphicsSceneDragDropEvent *event )
{
    if( event->mimeData()->hasFormat( ITEMDRAGMIMETYPE ))
        event->acceptProposedAction();
}

void DragDropScene::dragMoveEvent( QGraphicsSceneDragDropEvent *event )
{
    dragEnterEvent( event );
}

ЗЫЗЫ: если возникнут проблемы, тогда можно будет и наследование QMimeData сделать, но пока не видно, откуда бы они возникли, они чисто теоретические
« Последнее редактирование: Июль 21, 2011, 11:21 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #1 : Июль 21, 2011, 10:55 »

сделал по вашему совету, вроде работает, но не хватает одной детали:
мне нужно перетаскивать итем внутри сцены и бросать на другие итемы, как сделать что бы при перетаскивании итем тоже передвигался, пока только курсор движется...
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #2 : Июль 21, 2011, 11:20 »

завести в ресурсах иконку для изображения айтема во время перемещения, и объекту класса QDrag (он неизбежно уже есть) установить её в обработчике mouseMoveEvent(QGraphicsSceneMouseEvent *event) с помощью метода void QDrag::setPixmap ( const QPixmap & pixmap ) перед вызовом QDrag::exec()

в моем примере в первом сообщении это строка drag->setPixmap( QPixmap( pic ) );

если надо именно текущее изображение объекта, то соответственно нарисовать QPixmap тем же способом, как рисуется объект в его paintEvent() и передать его в setPixmap
« Последнее редактирование: Июль 21, 2011, 11:23 от Гурман » Записан

2^7-1 == 127, задумайтесь...
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #3 : Июль 21, 2011, 11:51 »

т.е. сам итем водить не получится?
Записан
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #4 : Июль 21, 2011, 12:06 »

так, сделал как хотел - теперь итем дропается на другой итем.
но возникла другая проблема - итем после того как дропнул, больше не могу перетаскивать.
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #5 : Июль 21, 2011, 13:07 »

parent другой стал
Записан

2^7-1 == 127, задумайтесь...
Fregloin
Супер
******
Offline Offline

Сообщений: 1025


Просмотр профиля
« Ответ #6 : Июль 21, 2011, 14:01 »

т.е. мне нужно сделать принудительно parent сцену а не итем, после этого можно тянуть?
Записан
Гурман
Гуру общения
******
Offline Offline

Сообщений: 1442

Qt 2.2, 3.3, 4.5, 4,7, 4.8, 5.3, 5.6, 5.9, 5.12


Просмотр профиля
« Ответ #7 : Июль 21, 2011, 16:18 »

можно и так, но это уже смотря что надо получить в результате, от целей зависит
Записан

2^7-1 == 127, задумайтесь...
Страниц: [1]   Вверх
  Печать  
 
Перейти в:  


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