Results 1 to 8 of 8

Thread: QGraphicsItem geometry change implementation

  1. #1
    Join Date
    Mar 2016
    Posts
    16
    Thanks
    3
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default QGraphicsItem geometry change implementation

    I am trying to figure out how objects in a QGraphics Scene/View can be manipulated and redrawn.

    From what I have learnt so far, when a QGraphicsItem needs to be added to the scene,

    1. The object is derived from QGraphicsItem.
    2. boundingRect(), and paint() needs to be reimplemented.
    3. If some of the sizes need to be changed, use prepareGeometry(), and update().

    So, I am working with two actions. One to add a box to the scene, and the other to increase the size when selected.

    I tried to get it to work in one application and it did not work.(diagram.zip). The sizes of the item seem to reset before painting. I can see this if I keep increasing the size and trap the code. However, under certain paths it seem to work. For example, if I add a child to a box and select the parent, the size of the parent can be changed programmatically.

    However, I created the minimum code required and it worked.
    The code is in GrScene.zip

    Why is there a difference in behavior?

    Thanks in advance.
    Attached Files Attached Files

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    In this code:

    Qt Code:
    1. void DiagramWindow::increaseSize()
    2. {
    3.  
    4. QList<QGraphicsItem *> items = scene->selectedItems();
    5. if (items.count() == 1) {
    6. Node *selNode = dynamic_cast<Node *>(items.first());
    7. selNode->increaseSize();
    8. }
    9. return;
    10. }
    To copy to clipboard, switch view to plain text mode 

    What happens if the selected node is a child of another node? I think in that case, both nodes will be marked as selected so your count will be 2, not 1. Have you looked at the size of the count in the cases where "works" and "doesn't work"?

  3. #3
    Join Date
    Mar 2016
    Posts
    16
    Thanks
    3
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    The count does not seem to matter. However, the path it gets there to increase the size seems to.

    MainWindow::increaseSize() --> Node::increaseSize() - does not work. Actually it resets the size. No idea how that happens
    MainWindow::selectedNode() --> Node::increaseSize() - seems to work.


    If I go through the second path and try the first path, the sizes get reset.

    If I try to trace the code, it goes into the moc_ code. I am wondering if some of the variables are initialized here. I cannot trace the code all the way.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    The count does not seem to matter.
    Of course the count matters. Your code (in either example) will do nothing if the selected node count is not exactly 1.

    In your DiagramWindow:: selectedNode() code, you -are- resetting the node size to nodeh x nodew when the node has no children. And in addChild(), since you call this method -before- you add a child to it, you are resetting the size there as well.

    I'm not sure why you wrote selectedNode() that way, but it looks like some confused thinking about what should happen when you add a child node.

  5. #5
    Join Date
    Mar 2016
    Posts
    16
    Thanks
    3
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    Hi d_stranz,

    You are correct in that the size matters, and how the reset happens. Great catch.

    I'm not sure why you wrote selectedNode() that way, but it looks like some confused thinking about what should happen when you add a child node.
    Originally, the selectedNode() was used to return when a node is selected.

    I added code here to try out the code for increasing the size of the widget on selecting a node. So, this shows that I can actually increase the size of the widget. Then I went ahead and implemented a new QAction for that. Somehow using the same code the new path does not work.

    I was expecting the new QAction will do the same thing. The new path follows these two functions. Here the count is used only to isolate one selected item and the dynamic_cast is used to ensure it is of the correct type in the original example.

    For the values not to be reset, I commented the code in selectedNode().

    So, this is the path that does not work,

    Qt Code:
    1. void DiagramWindow::increaseSize()
    2. {
    3.  
    4. QList<QGraphicsItem *> items = scene->selectedItems();
    5. if (items.count() == 1) {
    6. Node *selNode = dynamic_cast<Node *>(items.first());
    7. selNode->increaseSize();
    8. }
    9. return;
    10. }
    11.  
    12. void Node::increaseSize(void)
    13. {
    14. prepareGeometryChange();
    15. baseh = baseh + nodeh;
    16. basew = basew + nodew;
    17. update();
    18. return;
    19. }
    To copy to clipboard, switch view to plain text mode 

    and this is the path that works in the second, isolated example.

    Qt Code:
    1. void MainWindow::on_actionIncrease_Size_triggered()
    2. {
    3. QList<QGraphicsItem *> items = scene->selectedItems();
    4. if (items.count() == 1) {
    5. Node *selNode = dynamic_cast<Node *>(items.first());
    6. selNode->increaseSize();
    7. }
    8. return;
    9. }
    10. void Node::increaseSize()
    11. {
    12. prepareGeometryChange();
    13. baseh += nodeh;
    14. basew += nodew;
    15. update();
    16. }
    To copy to clipboard, switch view to plain text mode 


    Added after 40 minutes:


    So, I thought the reset problem was over. It ain't.

    The new selectedNode() function does what the original code intended to do, simply returns a pointer to the selected node.
    Qt Code:
    1. Node *DiagramWindow::selectedNode() const
    2. {
    3.  
    4. QList<QGraphicsItem *> items = scene->selectedItems();
    5. if (items.count() == 1) {
    6. Node *dad = dynamic_cast<Node *>(items.first());
    7. return dad;
    8. } else
    9. return 0;
    10. }
    To copy to clipboard, switch view to plain text mode 

    If I break at Node::increaseSize(), the baseh, basew do increase, but somewhere they get reset, and in the next cycle, the values are the original values.
    Last edited by Narada; 11th April 2016 at 23:54.

  6. #6
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    Here the count is used only to isolate one selected item
    And if for any reason at all, the count is NOT 1, nothing will be executed. Do us both a favor and put a
    Qt Code:
    1. qDebug() << "items.count() = " << items.count();
    To copy to clipboard, switch view to plain text mode 
    line in there after you retrieve the selected items, just to prove to both of us whether the count is anything other than one. You can't claim the code doesn't work when you don't demonstrate that the if() clause is ever executed.

    It also isn't clear how you get to DiagramWindow:: increaseSize() in the first place. Is this a slot? What signal is it connected to? Do you have any evidence that the method is ever called?

    the dynamic_cast is used to ensure it is of the correct type in the original example.
    Yes, but you should also realize that dynamic_cast<> returns a NULL pointer if the type is not correct, so your code as it stands now is guaranteed to blow up since you don't check for NULL but just go ahead and use the pointer no matter what.

    --Edit--

    Ummm, I just took a bit closer look at the DiagramWindow.cpp file you posted earlier. See if you can spot anything suspicious about this code:

    Qt Code:
    1. void DiagramWindow::createActions()
    2. {
    3. // ... stuff omitted
    4.  
    5. increaseSizeAction = new QAction(tr("Increase"),this);
    6. increaseSizeAction->setIcon(QIcon(":/images/increaseSize.png"));
    7. connect(increaseSizeAction, SIGNAL(triggered(bool)),
    8. this, SLOT(increaseSize()));
    9.  
    10.  
    11. decreaseSizeAction = new QAction(tr("Decrease"),this);
    12. decreaseSizeAction->setIcon(QIcon(":/images/decreaseSize.png"));
    13. connect(increaseSizeAction, SIGNAL(triggered(bool)),
    14. this, SLOT(decreaseSize()));
    15.  
    16. normalSizeAction = new QAction(tr("Normal"),this);
    17. normalSizeAction->setIcon(QIcon(":/images/normalSize.png"));
    18. connect(increaseSizeAction, SIGNAL(triggered(bool)),
    19. this, SLOT(normalSize()));
    20. }
    To copy to clipboard, switch view to plain text mode 
    Last edited by d_stranz; 12th April 2016 at 05:22.

  7. The following user says thank you to d_stranz for this useful post:

    Narada (12th April 2016)

  8. #7
    Join Date
    Mar 2016
    Posts
    16
    Thanks
    3
    Qt products
    Qt4 Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    my action has a copy/paste error!!!

    I should stick to my daytime job.


    Added after 8 minutes:


    The interesting thing is how I convinced myself on the proper connection to the slots. I put a break point in my destination function, node::increaseSize() and thought if I get there I set it up correct. Wrong!!!
    Last edited by Narada; 12th April 2016 at 15:21.

  9. #8
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    5,230
    Thanks
    302
    Thanked 864 Times in 851 Posts
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicsItem geometry change implementation

    And your copy/paste error completely explains what you were seeing. Slots are executed in the order that connections are made, so the increaseSizeAction first increased the size, then decreased the size, then reset it...

    It is a good practice to check the call stack when you are puzzled about problems like this. You would have seen this series of calls and found the answer much more quickly.

Similar Threads

  1. the minimized dialog can not change the geometry?
    By wearilybird in forum Qt Programming
    Replies: 0
    Last Post: 23rd September 2014, 08:36
  2. Change implementation according to different platform
    By stereoMatching in forum Qt Quick
    Replies: 1
    Last Post: 27th December 2013, 16:28
  3. Replies: 0
    Last Post: 8th July 2013, 14:44
  4. Can't change QHBoxLayout geometry
    By gutiory in forum Newbie
    Replies: 6
    Last Post: 17th June 2010, 09:37
  5. GraphicsView: Notifying geometry change to parent group
    By Gopala Krishna in forum Qt Programming
    Replies: 8
    Last Post: 12th August 2007, 13:04

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.