Russian Qt Forum

Qt => Пользовательский интерфейс (GUI) => Тема начата: Гурман от Июнь 23, 2011, 17:47



Название: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Гурман от Июнь 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 сделать, но пока не видно, откуда бы они возникли, они чисто теоретические


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Fregloin от Июль 21, 2011, 10:55
сделал по вашему совету, вроде работает, но не хватает одной детали:
мне нужно перетаскивать итем внутри сцены и бросать на другие итемы, как сделать что бы при перетаскивании итем тоже передвигался, пока только курсор движется...


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Гурман от Июль 21, 2011, 11:20
завести в ресурсах иконку для изображения айтема во время перемещения, и объекту класса QDrag (он неизбежно уже есть) установить её в обработчике mouseMoveEvent(QGraphicsSceneMouseEvent *event) с помощью метода void QDrag::setPixmap ( const QPixmap & pixmap ) перед вызовом QDrag::exec()

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

если надо именно текущее изображение объекта, то соответственно нарисовать QPixmap тем же способом, как рисуется объект в его paintEvent() и передать его в setPixmap


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Fregloin от Июль 21, 2011, 11:51
т.е. сам итем водить не получится?


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Fregloin от Июль 21, 2011, 12:06
так, сделал как хотел - теперь итем дропается на другой итем.
но возникла другая проблема - итем после того как дропнул, больше не могу перетаскивать.


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Гурман от Июль 21, 2011, 13:07
parent другой стал


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Fregloin от Июль 21, 2011, 14:01
т.е. мне нужно сделать принудительно parent сцену а не итем, после этого можно тянуть?


Название: Re: Перетаскивание указателя на QGraphicsItem из одной QGraphicsScene в другую
Отправлено: Гурман от Июль 21, 2011, 16:18
можно и так, но это уже смотря что надо получить в результате, от целей зависит