Qt - перетаскивание с помощью фреймворка графического представления

Я пытаюсь сделать простой перетаскиваемый элемент, используя графическую среду. Вот код того, что я делал до сих пор:

Класс виджета:

class Widget : public QWidget
{
    Q_OBJECT

public:
    Widget(QWidget *parent = 0);
    ~Widget();

};

Widget::Widget(QWidget *parent)
    : QWidget(parent)
{
    DragScene *scene = new DragScene();
    DragView *view = new DragView();
    QHBoxLayout *layout = new QHBoxLayout();

    DragItem *item = new DragItem();
    view->setAcceptDrops(true);
    scene->addItem(item);
    view->setScene(scene);
    layout->addWidget(view);
    this->setLayout(layout);

}

Widget::~Widget()
{
}

Класс DragView:

class DragView : public QGraphicsView
{
public:
    DragView(QWidget *parent = 0);
};

DragView::DragView(QWidget *parent) : QGraphicsView(parent)
{
    setRenderHints(QPainter::Antialiasing);
}

DragScene класс:

class DragScene : public QGraphicsScene
{
public:
    DragScene(QObject* parent = 0);

protected:
    void dragEnterEvent(QGraphicsSceneDragDropEvent *event);
    void dragMoveEvent(QGraphicsSceneDragDropEvent *event);
    void dragLeaveEvent(QGraphicsSceneDragDropEvent *event);
    void dropEvent(QGraphicsSceneDragDropEvent *event);
};

DragScene::DragScene(QObject* parent) : QGraphicsScene(parent)
{
}

void DragScene::dragEnterEvent(QGraphicsSceneDragDropEvent *event){
}

void DragScene::dragMoveEvent(QGraphicsSceneDragDropEvent *event){
}

void DragScene::dragLeaveEvent(QGraphicsSceneDragDropEvent *event){
}

void DragScene::dropEvent(QGraphicsSceneDragDropEvent *event){
    qDebug() << event->pos();
    event->acceptProposedAction();
    DragItem *item = new DragItem();
    this->addItem(item);
    // item->setPos(event->pos()); before badgerr's tip
    item->setPos(event->scenePos());
}

DragItem класс:

class DragItem : public QGraphicsItem
{
public:
    DragItem(QGraphicsItem *parent = 0);
    QRectF boundingRect() const;
    void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);

protected:
    void mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event);
    void mouseMoveEvent(QGraphicsSceneMouseEvent *event);
    void mousePressEvent(QGraphicsSceneMouseEvent *event);
    void mouseReleaseEvent(QGraphicsSceneMouseEvent *event);
};

DragItem::DragItem(QGraphicsItem *parent) : QGraphicsItem(parent)
{
    setFlag(QGraphicsItem::ItemIsMovable);
}

QRectF DragItem::boundingRect() const{
    const QPointF *p0 = new QPointF(-10,-10);
    const QPointF *p1 = new QPointF(10,10);
    return QRectF(*p0,*p1);
}

void DragItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){
    if(painter == 0)
        painter = new QPainter();
    painter->drawEllipse(QPoint(0,0),10,10);
}

void DragItem::mouseDoubleClickEvent(QGraphicsSceneMouseEvent *event){

}

void DragItem::mouseMoveEvent(QGraphicsSceneMouseEvent *event){
}

void DragItem::mousePressEvent(QGraphicsSceneMouseEvent *event){
    QMimeData* mime = new QMimeData();
    QDrag* drag = new QDrag(event->widget());
    drag->setMimeData(mime);
    drag->exec();
}

void DragItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){
}

main.cpp создает экземпляр виджета и показывает его. Когда я пытаюсь перетащить круг, приложение просто создает еще один круг над исходным, независимо от того, где я отпускаю перетаскивание. qDebug () в dropEvent () DragScene показывает QPointF (0,0) каждый раз, когда перетаскивание заканчивается. Мне трудно понять, что именно я должен делать, какие классы я должен подклассифицировать, какие методы необходимо переопределить, чтобы эта работа работала. документация по этому поводу не очень подробна. Я хотел бы знать, как это работает, и если есть какой-нибудь другой, более полный ресурс, чтобы узнать о структуре графического представления, помимо официальной документации (что отлично, кстати, но было бы здорово, если бы был более подробный трактат по этому поводу).

РЕДАКТИРОВАТЬ:

Следуя совету Badgerr, я заменил item-> pos () в DragScene :: dropEvent () на item-> scenePos (), теперь событие drop создает новый круг в месте перетаскивания, что более или менее то, что я хотел. Но исходный круг все еще на месте, и пока выполняется перетаскивание, элемент не следует за курсором мыши.

В документации QGraphicsSceneDragDropEvent говорится, что pos () должен возвращать позицию курсора относительно представления, отправившего событие, которое, если я не ошибаюсь, не должно быть (0,0) все время. Странный.

Я читал в сообщении на форуме, что вы можете использовать QDrag :: setPixMap (), чтобы показать что-то во время перетаскивания, и в примерах я видел, как изображения устанавливаются как растровые, но как мне сделать растровое изображение таким же, как графический элемент Я должен тащить?


person liewl    schedule 28.04.2010    source источник


Ответы (1)


Существует пример с Qt Assistant, называемый «Пример робота с перетаскиванием», который, похоже, использует метод QDrag, я не знаю, смотрели ли вы уже на это.

edit: Простое наблюдение, похоже, вы создаете новый DragItem в своем DropEvent вместо использования mimeData () самого события, и поскольку ваш элемент отрисовывается в точке 0,0, это может объяснить, почему в этом месте появляется новый, независимо от того, куда вы бросаете DragItem.


Когда я писал похожую на эту штуку с перетаскиванием графики, я делал это немного по-другому. Может быть, это поможет вам:

Вместо использования QDrag я использовал только функции mousePressEvent, mouseReleaseEvent и mouseMoveEvent QGraphicsItem. Нажатие / отпускание мыши устанавливает флаг, указывающий состояние перетаскивания, и перемещение следует за процессом

  • вызвать prepareGeometryChange ();
  • обновить границы QGraphicsItem (моя функция boundingRect () возвращает эти границы. Все границы моих графических элементов находятся в пространстве QGraphicsScene)
  • вызовите update ();

Затем в моей функции paint () я рисую фигуру с помощью boundingRect ().

Извините, у меня нет образца кода, которым можно поделиться, я сделаю один, если у меня будет время.

person badgerr    schedule 29.04.2010
comment
Что касается DragItem, создаваемого в DragScene :: dropEvent (), в документации по QGraphicsItem говорится, что переопределенный метод paint () рисует в локальных координатах, также после того, как я добавляю объект DragItem в сцену, я перемещаю его в event- ›pos ( ). Я думал, что event- ›pos () должен быть точкой, где находится курсор, когда я отпускаю кнопку мыши, тем самым вызывая метод dropEvent (), но, возможно, это не так. - person liewl; 29.04.2010
comment
Попробуйте event- ›scenePos () вместо event-› pos (). - person badgerr; 30.04.2010
comment
Это сработало! Я обновлю вопрос, чтобы упомянуть об этом. Однако есть еще несколько нерешенных вопросов. - person liewl; 30.04.2010
comment
барсук, не могли бы вы привести пример того, как выполнять перетаскивание, как вы предлагаете? Спасибо. - person TheBigOnion; 21.12.2011