Qt - 与图形视图框架拖放 [英] Qt - drag and drop with graphics view framework

查看:179
本文介绍了Qt - 与图形视图框架拖放的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图使用图形框架创建一个简单的拖动项。这是到目前为止我做的代码:



Widget类:

  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类:

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

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)。我有一个很难的时间,试图了解我要做什么,我应该子类,哪些方法需要覆盖,使这项工作。有关此问题的文档不是很详细。我想知道如何使这项工作,如果有一些其他,更全面的资源来了解图形视图框架,除了官方文档(这是优秀的btw,但它会是巨大的,如果有一个更详细的



按照badgerr的建议,我更换了item-> pos()在DragScene :: dropEvent()with item-> scenePos()中,现在drop事件会在放置站点中创建一个新的圆圈,这或多或少是我想要的。



QGraphicsSceneDragDropEvent文档说,pos()是一个非常简单的方法,应该返回相对于发送事件的视图的光标位置,这除非我错了,不应该是(0,0)所有的时间。很奇怪。



我已经读过一个论坛帖子,你可以使用QDrag :: setPixMap()在拖动过程中显示的东西,在示例中我看到图片

解决方案

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



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






当我写了一个类似于这个图形拖动事情,我去了一个略有不同的方式。也许它会帮助你:



而不是使用QDrag的东西,我只使用mouseGressicsItem的mousePressEvent,mouseReleaseEvent和mouseMoveEvent函数。鼠标按下/释放设置一个标志,指示拖动状态,并按照




  • 调用prepareGeometryChange();

  • 更新QGraphicsItem的边界(我的boundingRect()函数返回这些边界所有我的图形项界限在QGraphicsScene空间)

  • / li>


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



对不起,我没有要分享的代码示例,如果我有时间,我会打一个。


I'm trying to make a simple draggable item using the graphics framework. Here's the code for what I did so far:

Widget class:

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:

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

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

DragScene class:

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:

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 instantiates a Widget and shows it. When I try to drag the circle, the app just creates another circle over the original one, regardless of where I release the drag. qDebug() in DragScene's dropEvent() shows QPointF(0,0) everytime the drag ends. I'm having a hard time trying to understand exactly what I have to do, which classes I should subclass, which methods needs to be overriden, to make this work. The documentation on this isn't very detailed. I'd like to know how to make this work, and if there's some other, more comprehensive resource to learn about the graphics view framework, besides the official documentation (which is excellent btw, but it would be great if there was a more detailed treatise on the subject).

EDIT:

Following badgerr's advice, I replaced item->pos() in DragScene::dropEvent() with item->scenePos(), now the drop event creates a new circle in the drop site, which is more or less what I wanted. But the original circle is still in place, and while the drag is in progress, the item doesn't follow the mouse cursor.

The QGraphicsSceneDragDropEvent documentation says that pos() should return the cursor position in relation to the view that sent the event, which, unless I got it wrong, shouldn't be (0,0) all the time. Weird.

I've read in a forum post that you can use QDrag::setPixMap() to show something during the drag, and in examples I've seen pictures being set as pixmaps, but how do I make the pixmap just like the graphics item I'm supposed to be dragging?

解决方案

There is an example with Qt Assistant called the "Drag and Drop Robot Example" which appears to use the QDrag method, I don't know if you've had a look at that already.

edit: Just a quick observation, you appear to be creating a new DragItem in your DropEvent, instead of using the mimeData() of the event itself, and since your item draws itself at 0,0, that might explain why you have a new one appearing at that position regardless of where you drop your DragItem.


When I wrote a graphics dragging thing similar to this, I went about it a slightly different way. Maybe it will help you:

Instead of using the QDrag stuff, I used only the mousePressEvent, mouseReleaseEvent, and mouseMoveEvent functions of QGraphicsItem. The mouse press/release set a flag indicating the drag state, and move followed a process of

  • call prepareGeometryChange();
  • update the bounds of the QGraphicsItem (my boundingRect() function returns these bounds. All my graphics item bounds are in QGraphicsScene space)
  • call update();

Then in my paint() function I draw a shape using the boundingRect().

Sorry I don't have a code sample to share, I'll knock one up if I get time.

这篇关于Qt - 与图形视图框架拖放的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆