2

I have a QGraphicsView area that displays some Item items. I would like to have mouse move implemented.

class Item
{
public:
    Item();
    void update();
    int x, y; // position
    int z; // order - should correspond also to index in item list
};

class Collection : public QGraphicsView
{
Q_OBJECT
public:
    Collection(QWidget *parent = 0);
    void update();
    QList<Item> *m_items;
protected:
    virtual void paintEvent(QPaintEvent * event);
    virtual void mousePressEvent(QMouseEvent * event);
    virtual void mouseReleaseEvent(QMouseEvent *event);
private:
    QPoint offset;
    int itemMoved;
};

trying:

void Collection::mousePressEvent(QMouseEvent* event)
{
    Item *currentItem = NULL;
    itemMoved = -1;
    foreach (QGraphicsItem *item, this->items(event->pos()))
    {

// never get into this loop since my items are not children of QGraphicsItem

        currentItem = dynamic_cast<Item*>(item);
        if (event->button() == Qt::LeftButton && currentItem)
        {
            itemMoved = currentItem->z;
            offset = event->pos();
        }
        else if (event->button() == Qt::RightButton)
        {
            // set right click stuff
        }
        else
        {
            event->ignore();
        }
        break;
    }
}

void CollectionView::mouseReleaseEvent(QMouseEvent* event)
{
    if(event->button() == Qt::LeftButton && itemMoved > 0)
    {
        m_items->at(itemMoved).x = event->pos().x();
        m_items->at(itemMoved).y = event->pos().y();

// So far multiple fails:

//    error: assignment of data-member 'Item::x' in read-only structure
//    error: assignment of data-member 'Item::y' in read-only structure
//    error: passing 'const Item' as 'this' argument of 'void Item::update()' discards qualifiers

        m_items->at(itemMoved).update();
        update();
    }
}

I would make my Item inherit QGraphicsItem but then I get errors about virtual functions that I don't know how to define (like boundingRect which would depend on the item contents... could be objects, images, svg, text... for some i know how to get the bounding rectangle but for others really idk)... Is that the only way to do this ?

How can I identify he items at the location of the mouse position, and what is preventing me to change the x and y for the item once mouse is moved ?

Thalia
  • 13,637
  • 22
  • 96
  • 190

1 Answers1

2

If you're going to implement everything yourself, you shouldn't be using QGraphicsView at all. If you wish to use QGraphicsView, there's no need to reimplement any of its virtual methods. Just use it as-is, and set the item's QGraphicsItem::ItemIsMovable flag.

A complete example is provided in this answer. The only reason for reimplementation of QGraphicsView::mousePressEvent was to implement creation of new items.

Community
  • 1
  • 1
Kuba hasn't forgotten Monica
  • 95,931
  • 16
  • 151
  • 313
  • I have been struggling to inherit from QGraphicsItem because I get errors about "can't allocate an object of abstract type Item" - so i end up having to define boundingRect and a number of other things I have no clue about how to define or how to call – Thalia Mar 06 '15 at 21:28
  • @Thalia The documentation tells you what these methods should do. You don't call them, the scene and the view does. If you have any definite questions, ask them separately. Feel free to look at the example code I've posted in the linked answer, and in [a multitude of other answers I have on QGraphicsViews](http://stackoverflow.com/search?q=user%3A1329652+QGraphicsView). – Kuba hasn't forgotten Monica Mar 06 '15 at 21:33
  • Defining the boundingRect means I have to define the bounding rectangle for all objects - and for some, like text and svg, I don't know how... with polygon I am still fighting – Thalia Mar 06 '15 at 21:34
  • I already had a "paint" but the QGraphicsItem version requires a QStyleOptionGraphicsItem *option that I don't know where to get from – Thalia Mar 06 '15 at 21:36
  • Sorry what do you mean ? about not deriving but using as is ? – Thalia Mar 06 '15 at 21:37
  • I'm sorry, I just wrote you should instantiate an abstract class - I should go to sleep... – LogicStuff Mar 06 '15 at 21:40
  • @Thalia I think you approach it the wrong way. `QStyleOptionGraphicsItem *option` is a parameter that is passed *to you*. You don't have to worry about it if your item is not styled. As for finding the bounding rectangle, it should be easy as well for anything you can think of. Just check in Qt's documentation for relevant methods. For example, `QFontMetricsF::boundingRect` . – Kuba hasn't forgotten Monica Mar 06 '15 at 21:41
  • I will have to read more about this to understand how to set it up... thank you for the examples, i will be back – Thalia Mar 06 '15 at 21:43
  • how does a single item look like? has text? polygon? both? more? – sithereal Mar 06 '15 at 23:20
  • I have managed to inherit from QGraphicsItem and my paint and anything else works. Mouse press gives me qDebug info about the item and mouse location, I get qDebug info in MouseRelease event - but the item does not move... I guess I sill must work on it – Thalia Mar 09 '15 at 16:13
  • @Thalia You don't need to process mouse events yourself. Did you declare the item movable? If you implement the mouse events, are you invoking the implementation of the base class? Otherwise it wont' work. Most likely, you need to remove your mouse event implementations, and it will just start to work. Your implementations are likely unnecessary anyway. – Kuba hasn't forgotten Monica Mar 09 '15 at 16:23