Page 1 of 2 12 LastLast
Results 1 to 20 of 21

Thread: select QGraphicsItems by mouseclick

  1. #1
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default select QGraphicsItems by mouseclick

    I wana to select QGraphicsItems by mouseclick, and then generate new QGraphicsItems as children of the one being clicked. It's supposed to be like this:

    I used to look for signals like isSelected or something, of course with no luck. Since QGraphicsItem even doesn't inherit QObject.
    Now I have no idea of how it could be implemented. Can anyone help?
    Many thanks in advance!
    Attached Images Attached Images
    Last edited by Shawn; 28th July 2007 at 07:11.

  2. #2
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    BTW, the rectangle is drawn this way:
    Qt Code:
    1. void test::drawRect(QGraphicsScene &scene, int x, int y, int m, int n)
    2. {
    3. QAbstractGraphicsShapeItem *i = scene.addRect( QRectF(x, y, m, n));
    4. i->setFlag(QGraphicsItem::ItemIsSelectable);
    5. i->setBrush( QColor(233,104,21) );
    6. i->setPen( QPen(QColor(246,153,90), 3));
    7. i->setZValue(2);
    8. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by Shawn; 28th July 2007 at 07:12.

  3. #3
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    You can use, QGraphicsScene::selectionChanged() signal and use QGraphicsScene::selectedItems() to get the selected item.

    One more better way is to subclass the required QGraphicsItems and provide the required functionality using mouse*Event handlers. Or may be implement QGraphicsItem::itemChange() to intercept selection and then take required action.

    Finally if you dont want to reimplement each and every shape items, you can create a custom item , implement the QGraphicsItem::sceneEventFilter() method to do appropriate things on mouse click and install this as event filter. (see QGraphicsItem::installSceneEventFilter( ) )
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  4. The following 3 users say thank you to Gopala Krishna for this useful post:

    aRestless (11th June 2010), cwnelatury (12th May 2009), Shawn (28th July 2007)

  5. #4
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    Gopala Krishna, Thanks for your quick reply!

    I tried the first way u gave:
    Qt Code:
    1. test::test(QWidget *parent, Qt::WFlags flags)
    2. : QMainWindow(parent, flags)
    3. {
    4. ui.setupUi(this);
    5. ......
    6. ui.graphicsView_3->setScene(&scene3);
    7. QObject::connect(&scene3, SIGNAL(selectionChanged()), this, SLOT(testslots()));
    8. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. void test::drawText(QGraphicsScene &scene, QString *str, int x, int y)
    2. {
    3. QGraphicsTextItem* i = scene.addText(*str);
    4. i->setPos(x, y);
    5. i->setZValue(3);
    6. }
    To copy to clipboard, switch view to plain text mode 
    Qt Code:
    1. void test::testslots()
    2. {
    3. QString tmp = "OK";
    4. drawText(scene3, &tmp, 0, 0);
    5. }
    To copy to clipboard, switch view to plain text mode 

    But after I change the selection, I mean I select the items one by another, nothing happens !
    Is there anything wrong ?

  6. #5
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    Is the slot being called atleast once ? I am asking this because the docs for selectionChanged() signal quote
    QGraphicsScene emits this signal only once for group selection operations. For example, if you set a selection area, select or unselect a QGraphicsItemGroup, or if you add or remove from the scene a parent item that contains several selected items, selectionChanged() is emitted only once after the operation has completed (instead of once for each item).
    A better way to verify if the slot was called is to use qDebug() in the slot.
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  7. #6
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    Checkout this. This example works for me

    object.h
    Qt Code:
    1. #include <QObject>
    2. #include <QMessageBox>
    3. class Receiver : public QObject
    4. {
    5. Q_OBJECT
    6. public:
    7. Receiver() : QObject()
    8. {}
    9.  
    10. public slots:
    11. void test()
    12. {
    13. QMessageBox::information(0, "This", "Is working");
    14. }
    15. };
    To copy to clipboard, switch view to plain text mode 

    main.cpp
    Qt Code:
    1. #include <QtGui>
    2. #include "object.h"
    3.  
    4. int main(int argc, char *argv[])
    5. {
    6. QApplication app(argc, argv);
    7. QGraphicsScene sc(0,0,1055,768);
    8. Receiver r;
    9. QGraphicsView v(&sc);
    10. QObject::connect(&sc, SIGNAL(selectionChanged()), &r, SLOT(test()));
    11. QGraphicsLineItem *li = sc.addLine(10,25,326,230,QPen(Qt::green));
    12. QGraphicsRectItem *ri = sc.addRect(50,23,50,50,QPen(Qt::red));
    13. li->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
    14. ri->setFlags(QGraphicsItem::ItemIsMovable | QGraphicsItem::ItemIsSelectable | QGraphicsItem::ItemIsFocusable);
    15. v.show();
    16. return app.exec();
    17. }
    To copy to clipboard, switch view to plain text mode 
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  8. The following 2 users say thank you to Gopala Krishna for this useful post:

    cwnelatury (12th May 2009), Shawn (30th July 2007)

  9. #7
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    I checked the reference and found that the selectionChanged() signal is introduced since Qt4.3, and I am using Qt4.2 now

  10. #8
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    In that case you are better of to reimplement the item's itemChange method. Actually you can derive your item even from QObject and you can emit custom signal when selection changes.

    Qt Code:
    1. class MyCustomItem : public QObject, public QGraphicsItem
    2. {
    3. Q_OBJECT
    4. public:
    5. MyCustomItem()
    6. ..
    7.  
    8. signals:
    9. void selectionChanged(bool newState);
    10.  
    11. protected:
    12. QVariant itemChange(GraphicsItemChange change, const QVariant &value)
    13. {
    14. if (change == QGraphicsItem::ItemSelectedChange) {
    15. bool newState = value.toBool();
    16. //This sometimes might not be safe to emit signal
    17. //here since the state is still unchanged. Better option might
    18. //be to use a single shot timer to emit this signal rather than
    19. //emitting it directly
    20. emit selectionChanged(newState);
    21. }
    22. return QGraphicsItem::itemChange(change, value);
    23. }
    24. };
    To copy to clipboard, switch view to plain text mode 

    P.S: I'm not sure of my comment in the program though
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  11. The following 2 users say thank you to Gopala Krishna for this useful post:

    cwnelatury (12th May 2009), Shawn (30th July 2007)

  12. #9
    Join Date
    Oct 2006
    Location
    New Delhi, India
    Posts
    2,467
    Thanks
    8
    Thanked 334 Times in 317 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: select QGraphicsItems by mouseclick

    Another way of catching events is -
    Install filter on the scene, check if any item is presnt where the mouse is pressed. U can get the item by itemAt() function, and then perform the action u want.

    However from the thumbnail I see u have more of a tree structure kind items.
    I want to know why arent u using a tree itself ?? U can create a custom QTreeWidgetItem and have a pointer to the QGraphicsItem to it..

    like -
    class MyTreeWidgetItem : public QTreeWidgetItem
    {
    QGraphicsItem *pGraphicsItem;
    };

    and u can have a map of graphics items and tree nodes -
    QHash <QGraphicsItem *, MyTreeWidgetItem*> item_treeMap;

    Hope I am getting ur problem correctly .

  13. The following user says thank you to aamer4yu for this useful post:

    Shawn (31st July 2007)

  14. #10
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    Quote Originally Posted by aamer4yu View Post
    Another way of catching events is -
    Install filter on the scene, check if any item is presnt where the mouse is pressed. U can get the item by itemAt() function, and then perform the action u want.
    I guess this might not work. Actually even i stated above that eventFilter is an alternative.
    Since the event filter is called before the event handlers the item wont be selected when mouse is pressed and control reaches eventFilter. So you have no way here to determine whether the item is selected or not. You cant even execute the event handler in eventfilter since the handlers are protected/private.
    Please correct me if i am wrong

    EDIT: Sorry misread your post. You select the item just by coordinate right(using itemAt). I thought you were looking at selectedItems in the event handler. But you have to make sure that you are checking the button and also set the state of the item to selected.
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  15. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

  16. #11
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Smile Re: select QGraphicsItems by mouseclick

    I did what u said
    Qt Code:
    1. class MyRectItem : public QObject, public QAbstractGraphicsShapeItem
    2. {
    3. Q_OBJECT
    4. public:
    5. MyRectItem();
    6. signals:
    7. void selectionChanged(bool newState);
    8. protected:
    9. QVariant itemChange(GraphicsItemChange change, const QVariant &value)
    10. {
    11. if (change == QGraphicsItem::ItemSelectedChange)
    12. {
    13. bool newState = value.toBool();
    14. emit selectionChanged(newState);
    15. }
    16. return QGraphicsItem::itemChange(change, value);
    17. }
    18. };
    To copy to clipboard, switch view to plain text mode 

    Qt Code:
    1. void test::drawRect(QGraphicsScene &scene, int x, int y, int m, int n)
    2. {
    3. MyRectItem *i = scene.addRect( QRectF(x, y, m, n));
    4. i->setFlag(QGraphicsItem::ItemIsSelectable);
    5. i->setBrush( QColor(233,104,21) );
    6. i->setPen( QPen(QColor(246,153,90), 3));
    7. i->setZValue(2);
    8. }
    To copy to clipboard, switch view to plain text mode 

    and there is an error :
    error C2440: 'initializing' : cannot convert from 'QGraphicsRectItem *' to 'MyRectItem *'
    How can I deal with this ?
    I am not familiar with the multi-inheritance.
    Hope you can help me, and thanks in advance.
    Last edited by Shawn; 31st July 2007 at 08:23.

  17. #12
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    The scene.addRect returns new QGraphicsRectItem* which is now way connected to MyRectItem other than that they both have common base.
    To add any of your custom item use scene.addItem(new CustomItem()) (in your case new MyRectItem).

    One more thing , you don't seem to store any rect coordinates nor provide the required constructor. One way to tackle this is to inherit MyRectItem from QGraphicsRectItem rather that QAbstractGraphicsShapeItem and implement the constructors as needed
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  18. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

  19. #13
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    I inherite MyRectItem from and implement the constructor
    Qt Code:
    1. class MyRectItem : public QObject, public QGraphicsRectItem
    2. {
    3. Q_OBJECT
    4. public:
    5. MyRectItem(int x, int y, int w,int h)
    6. {
    7. QRectF(x, y, w, h);
    8. }
    9. ....
    10. };
    To copy to clipboard, switch view to plain text mode 

    and then
    Qt Code:
    1. void test::drawRect(QGraphicsScene &scene, int x, int y, int m, int n)
    2. {
    3. MyRectItem *i = new MyRectItem(x, y, m, n);
    4. scene.addItem(i);
    5. i->setFlag(QGraphicsItem::ItemIsSelectable);
    6. }
    To copy to clipboard, switch view to plain text mode 
    But there is no Rect now

  20. #14
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    I guess the following changes will fix your code
    Firstly your constructor

    Qt Code:
    1. MyRectItem(qreal x, qreal y, qreal w, qreal h) : QGraphicsRectItem(x,y,w,h)
    2. {}
    To copy to clipboard, switch view to plain text mode 
    and secondly set some pen and brush to the item
    Qt Code:
    1. i->setPen(QPen(Qt::darkBlue));
    To copy to clipboard, switch view to plain text mode 
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  21. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

  22. #15
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    Yes I 've set pen and brush to the item, I discard them just to make my post short

    And I revise the constructor as u said and it works !

    Thanks a lot

    the next problem is that :

    seems no signal is emited ?
    because when I select the MyRectItems one after another, and nothing happens?

    Singal and Slot definition and connection is as below.

    Latest:
    Qt Code:
    1. void test::drawRect(QGraphicsScene &scene, int x, int y, int m, int n)
    2. {
    3. MyRectItem *i = new MyRectItem(x, y, m, n);
    4. QObject::connect(i, SIGNAL(selectionChanged()), this, SLOT(testslots()));
    5. scene.addItem(i);
    6. ....
    7. }
    To copy to clipboard, switch view to plain text mode 
    Now it is OK ~
    Last edited by Shawn; 31st July 2007 at 10:11.

  23. #16
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    You used the wrong signature of signal in the connect statement.
    Shouldn't that be SIGNAL(selectionChanged(bool)) ?
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  24. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

  25. #17
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    Yes, I also change the signal to make it more simple...

    The problem is that the signal is emited whenever the selection of an item is changed, which also means that when I unselecte the item, the signal will also be emited.

    This is not the what I want, which I want exactly is that when I selected an item, which would be better, double click an item, there can be a signal, and then I can write some slots to deal with this signal.

  26. #18
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    Thats very easy to fix
    Qt Code:
    1. if(newState == true)
    2. emit itemSelected();
    To copy to clipboard, switch view to plain text mode 
    Notice that i changed the signal name to be more meaningful. Change everywhere as needed
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  27. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

  28. #19
    Join Date
    May 2007
    Posts
    91
    Thanks
    60
    Qt products
    Qt4
    Platforms
    Windows

    Default Re: select QGraphicsItems by mouseclick

    Thanks a lot !
    It works fine.

    Anyway, if I want to selected that item by double click, what should I do ?

    PS:seems I am really lazy. But maybe I should know the way to do it first, then I can find out why I should do it that way, right ?

  29. #20
    Join Date
    Aug 2006
    Location
    Bangalore,India
    Posts
    419
    Thanks
    37
    Thanked 53 Times in 40 Posts
    Qt products
    Qt3 Qt4
    Platforms
    Unix/X11

    Default Re: select QGraphicsItems by mouseclick

    I guess you can do it yourself if you get to know some common mistakes

    Anyway for your question the answer involves
    QGraphicsItem::mouseDoubleClickEvent()
    QGraphicsItem::setSelected()
    I hope you got the approach
    The biggest difference between time and space is that you can't reuse time.
    -- Merrick Furst

  30. The following user says thank you to Gopala Krishna for this useful post:

    Shawn (31st July 2007)

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.