0

我正在尝试使用图形框架制作一个简单的可拖动项目。这是我到目前为止所做的代码:

小部件类:

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()
{
}

拖动视图类:

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());
}

拖动项类:

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 实例化一个 Widget 并显示它。当我尝试拖动圆圈时,应用程序只会在原始圆圈上创建另一个圆圈,无论我在哪里释放拖动。每次拖动结束时,DragScene 的 dropEvent() 中的 qDebug() 都会显示 QPointF(0,0)。我很难准确地理解我必须做什么,我应该子类化哪些类,需要覆盖哪些方法,以使这项工作正常进行。这方面的文档不是很详细。我想知道如何完成这项工作,以及是否还有其他更全面的资源来了解图形视图框架,除了官方文档(顺便说一句,这很好,但如果有更详细的论题)。

编辑:

按照 badrr 的建议,我将 DragScene::dropEvent() 中的 item->pos() 替换为 item->scenePos(),现在 drop 事件在 drop 站点中创建了一个新圆圈,这或多或少是我想要的。但原来的圆圈还在原处,并且在拖动过程中,该项目没有跟随鼠标光标。

QGraphicsSceneDragDropEvent 文档说 pos() 应该返回与发送事件的视图相关的光标位置,除非我弄错了,否则它不应该一直是 (0,0)。诡异的。

我在论坛帖子中读到,您可以使用 QDrag::setPixMap() 在拖动期间显示某些内容,并且在示例中我看到图片被设置为像素图,但是如何制作像素图就像图形项一样我应该是拖吗?

4

1 回答 1

1

Qt 助手有一个名为“拖放机器人示例”的示例,它似乎使用了 QDrag 方法,我不知道您是否已经看过。

编辑:只是快速观察一下,您似乎是在 DropEvent 中创建一个新的 DragItem,而不是使用事件本身的 mimeData(),并且由于您的项目在 0,0 处绘制自身,这可能解释了为什么您有一个新的无论您将 DragItem 放在何处,都会出现在该位置。


当我写一个与此类似的图形拖动的东西时,我用了一种稍微不同的方式。也许它会帮助你:

我没有使用 QDrag 的东西,而是只使用了 QGraphicsItem 的 mousePressEvent、mouseReleaseEvent 和 mouseMoveEvent 函数。鼠标按下/释放设置一个指示拖动状态的标志,移动遵循一个过程

  • 调用 prepareGeometryChange();
  • 更新 QGraphicsItem 的边界(我的 boundingRect() 函数返回这些边界。我所有的图形项边界都在 QGraphicsScene 空间中)
  • 调用更新();

然后在我的paint() 函数中,我使用boundingRect() 绘制一个形状。

抱歉,我没有要分享的代码示例,如果有时间我会敲一个。

于 2010-04-29T08:10:06.793 回答