Qt - 拖放图形视图框架

时间:2010-04-28 18:59:41

标签: c++ qt qgraphicsview

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

小部件类:

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

编辑:

根据badgerr的建议,我使用item-&gt; scenePos()替换了DragScene :: dropEvent()中的item-&gt; pos(),现在drop事件在drop网站中创建了一个新的圆圈,这或多或少我想要的是什么但是原始圆圈仍然存在,当拖动正在进行时,该项目不会跟随鼠标光标。

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

我在一篇论坛帖子中看到你可以使用QDrag :: setPixMap()在拖动过程中显示一些内容,在示例中我看到图片被设置为pixmaps,但是我如何让像素图像我应该拖动的图形项目?

1 个答案:

答案 0 :(得分:1)

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

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


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

我没有使用QDrag的东西,只使用了QGraphicsItem的mousePressEvent,mouseReleaseEvent和mouseMoveEvent函数。鼠标按下/释放设置指示拖动状态的标志,然后按

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

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

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