Results 1 to 14 of 14

Thread: QGraphicRectItem update colour in foreach statement

  1. #1
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default QGraphicRectItem update colour in foreach statement

    Good day everyone


    I am trying to change the colour of the QGraphicsRectItems that is on a scene. QGraphicsRectItems are nodes of a network, I want that each item to be updated by a colour indicating status of the node. my question how do i write a code that will update and iterate to the next item on the scene but keep the update ? THis one below it updates them all at the same time, i mean if one is green it turns all green or if one is red it turns all red which is not desired. it does not update each item at a time and keep the status and pass to the next, which is i would like to see. my code is below


    Qt Code:
    1. else if (_eType == QSubscription::UPDATED_TITLES)
    2. {
    3. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    4. m_pLinkStateListModel->addTitle(pState);
    5.  
    6.  
    7. foreach(QGraphicsItem *item,scene->items()) // foreach statement that updates all at the same time
    8. {
    9.  
    10. QGraphicsRectItem *rect = qgraphicsitem_cast<QGraphicsRectItem *>(item);
    11. if (!rect)
    12. continue;
    13. getTitleDescriptionColor(pState, m_backgroundColor, rect);
    14. }
    To copy to clipboard, switch view to plain text mode 

    The function that gets the colour (getTitleDescriptionColour) is


    Qt Code:
    1. QColor getTitleDescriptionColor(const DM::Object *_pTitle, const QColor &_colorBackground, QGraphicsRectItem *_row)
    2. {
    3.  
    4. QColor ret = _colorBackground;
    5.  
    6. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    7. {
    8.  
    9. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    10.  
    11.  
    12. if (pState->m_eState == C2DM::LinkState::EIS_GOOD)
    13. {
    14. ret = QColor(Qt::green).darker(120);
    15. _row->setBrush(ret);
    16. }
    17. else if (pState->m_eState == C2DM::LinkState::EIS_BUSY)
    18. {
    19. ret = QColor(Qt::yellow).darker(120);
    20. _row->setBrush(ret);
    21. }
    22. else
    23. {
    24. ret = QColor(Qt::red).darker(120);
    25. _row->setBrush(ret);
    26. }
    27.  
    28. }
    29. else if (CORE::checkPtrType<C2DM::RouteState>(_pTitle) == true)
    30. {
    31. C2DM::RouteState *pState = (C2DM::RouteState*)_pTitle;
    32.  
    33. if (pState->m_bEnabled == false)
    34. {
    35. ret = QColor(Qt::blue).lighter(120);
    36. }
    37. else if ((pState->m_eTxLinkState != C2DM::LinkState::EInterfaceState::EIS_GOOD) ||
    38. (pState->m_eRxLinkState != C2DM::LinkState::EInterfaceState::EIS_GOOD))
    39. {
    40. ret = QColor(Qt::yellow).darker(120);
    41. }
    42. else
    43. {
    44. ret = QColor(Qt::green).darker(120);
    45. }
    46.  
    47. }
    48.  
    49. return ret;
    50. }
    To copy to clipboard, switch view to plain text mode 

  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: QGraphicRectItem update colour in foreach statement

    Your logic in the getTitleDescriptionColor() is suspect. In the first half of it, your determine the color, and set a brush on the rectangle. In the second half of it, you determine the color but don't do anything with the rectangle, and in the calling function, you call the routing and completely ignore the return value.

    You haven't shown much context for the calling function, just one else-if clause, so are you sure this is where the rect colors are being set and not in some other clause? The part of the getTitle...() method that actually sets rect colors seems to be OK.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    Hello d_stranz


    I appreciate a lot for your response,thank you. The second half of getTitleDescriptionColor() is not adding the QGraphicsRectItems yet only the first part adds successfully, I was still going to check why it is not adding the items, but the first part of it adds them successfully ,thank you for pointing out my error there.

    On your question, I also call method addRect() which adds them on the scene and gives them color(see code), and I wanted to now only update the color based on the status of the link by calling method getTitleDescriptionColor(pState, m_backgroundColor, rect); with the foreach statement

    I do not understand what you mean by your statement(and in the calling function, you call the routing and completely ignore the return value.), how do I ignore the return value?

    Please find my attachment to see what i have so far. I have attached how the links(QGraphicsRectItems) are added on addRect(pState); statement as explained in the commentary below, the attachment also shows that all items are green at the same time, which is not true because other links are down, it supposed to show red to whomever is disconnected and green to where there is connection.

    Qt Code:
    1. void GatewayWidget::receivedTitlesEx(const QString &_rStrDescription, const CORE::Time &_rSimTime, const QList<std::shared_ptr<DM::Object> > &_rTitles, int _eType)
    2. {
    3.  
    4. if (_rStrDescription == "LINK.*.STATE")
    5. {
    6. foreach (const std::shared_ptr<DM::Object> &objPtr, _rTitles)
    7. {
    8.  
    9. if (CORE::checkPtrType<C2DM::LinkState>(objPtr) == true)
    10. {
    11. if (_eType == QSubscription::NEW_TITLES)
    12. {
    13. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    14.  
    15. addRect(pState);// this is where i call the method that adds the QGraphicsRectItem(nodes) on the scene
    16.  
    17. }
    18. else if (_eType == QSubscription::UPDATED_TITLES)// this clause updates the status of the links of the network(QGraphicsRectItems) , for instance when there is a physical connection of a link or disconnection. Disconnection is red,connected green.That is where I want the colors of the QGraphicsRectItems to change as the status changes
    19. {
    20. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    21.  
    22.  
    23.  
    24. foreach(QGraphicsItem *item, scene->items())// this is the foreach that i call when trying to update each QGraphicsRectItem on the scene, which it does update but it keeps alternating the colors at the same time
    25. {
    26.  
    27. QGraphicsRectItem *rect = qgraphicsitem_cast<QGraphicsRectItem *>(item);
    28. if (!rect)
    29. continue;
    30.  
    31. getTitleDescriptionColor(pState, m_backgroundColor, rect);
    32. }
    33.  
    34. }
    35. else if (_eType == QSubscription::DELETED_TITLES)// still yet to implement a delete node(QGraphicsRectItem)
    36. {
    37. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    38.  
    39.  
    40. }
    41. }
    42.  
    43. }
    44.  
    45.  
    46.  
    47. }
    48. else if (_rStrDescription == "ROUTE.*.STATE") //still yet to implement routes was first starting with the links
    49. {
    50. foreach (const std::shared_ptr<DM::Object> &objPtr, _rTitles)
    51. {
    52. if (CORE::checkPtrType<C2DM::RouteState>(objPtr) == true)
    53. {
    54. if (_eType == QSubscription::NEW_TITLES)
    55. {
    56. C2DM::RouteState *pRoute = (C2DM::RouteState*)objPtr->_clone();
    57.  
    58.  
    59.  
    60. }
    61. else if (_eType == QSubscription::UPDATED_TITLES)
    62. {
    63. C2DM::RouteState *pRoute = (C2DM::RouteState*)objPtr->_clone();
    64.  
    65.  
    66.  
    67. }
    68. else if (_eType == QSubscription::DELETED_TITLES)
    69. {
    70. C2DM::RouteState *pRoute = (C2DM::RouteState*)objPtr->_clone();
    71.  
    72. }
    73. }
    74.  
    75.  
    76.  
    77. }//end for each statement
    78. }// end else if
    To copy to clipboard, switch view to plain text mode 

    addRect(); method. This method adds links(QGraphicsReciItems) on the scene and adds color to them on startup. The color is supposed to update as links may be disconnected or connected which is what I am trying to achieve.
    Qt Code:
    1. void GatewayWidget::addRect(DM::Object *_pTitle)
    2. {
    3. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    4. {
    5.  
    6. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    7.  
    8.  
    9. QGraphicsTextItem *textColor = scene->addText(QString::fromStdString(pState->m_strLinkId));
    10.  
    11. int x = (qrand() % 4);
    12. int pos = (x * 75) - 75 / 2;
    13. textColor->setPos(400, pos + 200);
    14. textColor->setFlag(QGraphicsItem::ItemIsMovable);
    15. textColor->setFlag(QGraphicsItem::ItemIsSelectable);
    16. QGraphicsRectItem *rectangleColor = new QGraphicsRectItem(QRectF(0, 0, 50, 50), textColor);
    17.  
    18.  
    19. rectangleColor->setPos(0, 25);
    20. //rectangleColor->setFlag(pState::ItemIsMovable);
    21. rectangleColor->setFlag(QGraphicsItem::ItemIsSelectable);
    22.  
    23. getTitleDescriptionColor(pState, m_backgroundColor, rectangleColor);// I add colour on startup based on the initial state of the link
    24.  
    25.  
    26. }
    27. else if (CORE::checkPtrType<C2DM::RouteState>(_pTitle) == true)
    28. {
    29. C2DM::RouteState *pRoute = (C2DM::RouteState*)_pTitle;
    30.  
    31. QGraphicsRectItem *rectangle;
    32. QGraphicsRectItem *rectangle1;
    33. QPen pointpen(Qt::green);
    34. pointpen.setWidth(4);
    35. QPen linepen(Qt::red);
    36. linepen.setWidth(2);
    37. QColor ret = m_backgroundColor;
    38.  
    39.  
    40. text = scene->addText(QString::fromStdString(pRoute->m_strSource));
    41. text->setPos(600, (qrand() % 400));
    42.  
    43. text1 = scene->addText(QString::fromStdString(pRoute->m_strDestination));
    44. text1->setPos(900, (qrand() % 400));
    45.  
    46.  
    47. QString MessageCountSrc = QString::number(pRoute->m_dTxBps);
    48. rectangle = new QGraphicsRectItem(QRectF(0, 0, 60, 60), text1);
    49.  
    50. rectangle->setPos(0, 25);
    51. //rectangle->setBrush(greenBrush);
    52. rectangle->setFlag(QGraphicsItem::ItemIsSelectable);
    53.  
    54.  
    55.  
    56. QString MessageCount = QString::number(pRoute->m_uMsgCount);
    57. rectangle1 = new QGraphicsRectItem(QRectF(0, 0, 60, 60), text);
    58.  
    59. rectangle1->setPos(0, 25);// sets position of the name of the link e.g HS1
    60.  
    61. rectangle1->setFlag(QGraphicsItem::ItemIsSelectable);
    62.  
    63. //scene->update();
    64.  
    65. line->setLine(QLineF(rectangle1->scenePos(), rectangle->scenePos()));
    66.  
    67. line->setZValue(-1);//sets the line behind the rectangle box
    68. //scene->addLine(myLine, pointpen);
    69. scene->addItem(line);
    70.  
    71. getTitleDescriptionColor(pRoute, m_backgroundColor, rectangle1);
    72.  
    73. }
    74. }
    To copy to clipboard, switch view to plain text mode 
    Attached Images Attached Images

  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: QGraphicRectItem update colour in foreach statement

    how do I ignore the return value?
    The getTitleDescriptionColor() method returns a QColor (as "ret"). In your function that calls this method (line 31 of your first code blockabove and several places in the second code block), you do not assign this return value to anything. Basically, you are ignoring it. This means that the second half of the getTitleDescriptionColor method, where you compute the color only, is doing nothing that the calling routine (or anything else) actually uses.

    Qt Code:
    1. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    2. C2DM::RouteState *pRoute = (C2DM::RouteState*)objPtr->_clone();
    To copy to clipboard, switch view to plain text mode 

    Are these shared pointers? If not, then every one of these statements (except the first one, where you call addRect() afterwards) is probably a memory leak. Unless you have not posted the complete code in these parts of the if / else clauses, then here you create a "pState" or "pRoute" instance by cloning your object, then you do nothing with it. The pState" / "pRoute" variable goes out of scope at the end of that section of the conditional clause, so unless they are shared pointers, it is probably a memory leak. Depending on how often that function is called, it could be a big leak over time.

    But, OK, now I see your bug:

    - each time you call getTitleDescriptionColor(), you pass in -one- value for the LinkState, but you are calling the function for -every- rect in your scene, regardless of whether that LinkState applies to it or not. So the net result of iterating over all the rects will be to change every one of them to the same color based on that specific LinkState. When the LinkState changes again, every rect changes to the same color as a result.

    So what you need to do is to add an association between each rect and its specific LinkState value. You might be able to do this using QGraphicsItem::setData() for this, or a map< LinkState, QGraphicsRectItem *>, or some similar data structure. The basic problem is your code has no idea which rect has which LinkState.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. #5
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    Thank you again for your help,I appreciate.

    Concerning the cloning of the object under pRoute, I was still yet to implement the method. In my mind I wanted the links(Linkstate *pPstate) to work first, then implement the (Linkstate *pRoute) by also calling addRect(); I will comment it out to avoid the memory leaks, thank you.


    Thank you for the explanation of the bug, I was really confused. I am asking if you can help me with an example of how i can implement the
    Qt Code:
    1. void QGraphicsItem::setData ( int key, const QVariant & value ),
    To copy to clipboard, switch view to plain text mode 
    honestly I dont think i know how to do it.I am still a newbie,Please. Should int key be QGraphicsRectItem and const QVariant & value be the color? should this method be implemented outside the calling function and the call it on the foreach?

    Thanks in advance for your help!

  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: QGraphicRectItem update colour in foreach statement

    void QGraphicsItem::setData ( int key, const QVariant & value )
    This is a method in the base class for QGraphicsRectItem (QGraphicsItem). The "key" can be integer you want it to be. The reason it is there is to allow you to store more than one value for each item. Since you will probably be storing only one value in each QGraphicsRectItem, you can use 0 (zero) as the key.

    For the value, I would use the enum C2DM:: LinkState:: m_eType (eg. C2DM:: LinkState:: EIS_GOOD, EIS_BUSY, etc.). Your addRect() code would be modified to look like this:

    Qt Code:
    1. void GatewayWidget::addRect(DM::Object *_pTitle)
    2. {
    3. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    4. {
    5.  
    6. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    7.  
    8.  
    9. QGraphicsTextItem *textColor = scene->addText(QString::fromStdString(pState->m_strLinkId));
    10.  
    11. int x = (qrand() % 4);
    12. int pos = (x * 75) - 75 / 2;
    13. textColor->setPos(400, pos + 200);
    14. textColor->setFlag(QGraphicsItem::ItemIsMovable);
    15. textColor->setFlag(QGraphicsItem::ItemIsSelectable);
    16. QGraphicsRectItem *rectangleColor = new QGraphicsRectItem(QRectF(0, 0, 50, 50), textColor);
    17. rectangleColor->setData( 0, int( pState->m_eType ) ); // Automatically creates a QVariant<int>
    18. // etc. for the other rectangle
    To copy to clipboard, switch view to plain text mode 

    Your code for getTitleDescriptionColor() needs to check that the rectangle's LinkState type value matches the value you passed in:

    Qt Code:
    1. QColor getTitleDescriptionColor(const DM::Object *_pTitle, const QColor &_colorBackground, QGraphicsRectItem *_row)
    2. {
    3.  
    4. QColor ret = _colorBackground;
    5.  
    6. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    7. {
    8.  
    9. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    10.  
    11. // If the state type passed in does not match the state type stored in the rect, then do nothing
    12. int stateType = int( pState->m_eType );
    13. int rectState = _row->data( 0 ).toInt();
    14. if ( stateType != rectState )
    15. return ret;
    16.  
    17. // Otherwise, continue with the original code to change the rect color
    18.  
    19. // ...
    To copy to clipboard, switch view to plain text mode 

    You will need to add code to change the value stored in the QGraphicsRectItem whenever its LinkState changes.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  7. #7
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    Thank you for the response and generous help!

    I implemented it and it does change the color for a specific QGraphicsRectItem with its connection status(thank you), however when it updates the status correctly it also add new QGraphicsRectItems(see attachment),a repeat of QGraphicsRectItems that was on the scene but with an updated status. I called the addRect function on the update statement like this:
    Qt Code:
    1. void GatewayWidget::receivedTitlesEx(const QString &_rStrDescription, const CORE::Time &_rSimTime, const QList<std::shared_ptr<DM::Object> > &_rTitles, int _eType)
    2. {
    3.  
    4. if (_rStrDescription == "LINK.*.STATE")
    5. {
    6. foreach (const std::shared_ptr<DM::Object> &objPtr, _rTitles)
    7. {
    8.  
    9. if (CORE::checkPtrType<C2DM::LinkState>(objPtr) == true)
    10. {
    11. if (_eType == QSubscription::NEW_TITLES)
    12. {
    13. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    14.  
    15. addRect(pState);// this is the first call of the method that adds the QGraphicsRectItem(nodes) on the scene
    16.  
    17. }
    18. else if (_eType == QSubscription::UPDATED_TITLES)
    19. {
    20. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    21.  
    22. addRect(pState);//on updated status i call the addRect() again. When it updates the link status and change the color, it also adds the new QGraphicsRectItem when it is was already added on the first call of addRect() above.
    23. }
    To copy to clipboard, switch view to plain text mode 

    my understanding was that I am supposed to call addRect() again on the UPDATED_TITLES as seen on the else if clause above, am I correct?

    I think that on the addRect() function, I always add QGraphicsRectItems on the scene through this lines:
    Qt Code:
    1. QGraphicsTextItem *textColor = scene->addText(QString::fromStdString(pState->m_strLinkId));
    2. QGraphicsRectItem *rectangleColor = new QGraphicsRectItem(QRectF(0, 0, 50, 50), textColor);
    3. rectangleColor->setData(0, int(pState->m_eState));
    To copy to clipboard, switch view to plain text mode 

    then whenever I call addRect() it creates another QGraphicsRectItem with the updated status. my question is am I supposed to write another statement on addRect() that will check if the QGraphicsRectItems are already added on the scene, and if they are, then just change color only and not add a new QGraphicsRectItem?

    on your statement"You will need to add code to change the value stored in the QGraphicsRectItem whenever its LinkState changes." do you mean I should change the value int Rectstate when _eType changes here :
    Qt Code:
    1. }
    2. else if (_eType == QSubscription::UPDATED_TITLES) //this is where _eType changes(which is the LinkState),is this where I am supposed to write the code? how do I access the value [I]int rectState[/I] on this function?
    3. {
    4. C2DM::LinkState *pState = (C2DM::LinkState*)objPtr->_clone();
    5. addRect(pState);
    To copy to clipboard, switch view to plain text mode 

    function addRect() I updated it as you advised:
    Qt Code:
    1. void GatewayWidget::addRect(DM::Object *_pTitle)
    2. {
    3. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    4. {
    5.  
    6. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    7.  
    8.  
    9. QGraphicsTextItem *textColor = scene->addText(QString::fromStdString(pState->m_strLinkId));
    10.  
    11. int x = (qrand() % 4);
    12. int pos = (x * 75) - 75 / 2;
    13. textColor->setPos(400, pos + 200);
    14. textColor->setFlag(QGraphicsItem::ItemIsMovable);
    15. textColor->setFlag(QGraphicsItem::ItemIsSelectable);
    16. QGraphicsRectItem *rectangleColor = new QGraphicsRectItem(QRectF(0, 0, 50, 50), textColor);
    17. rectangleColor->setData(0, int(pState->m_eState));
    18.  
    19. rectangleColor->setPos(0, 25);
    20.  
    21. rectangleColor->setFlag(QGraphicsItem::ItemIsSelectable);
    22.  
    23. getTitleDescriptionColor(pState, m_backgroundColor, rectangleColor);
    24.  
    25.  
    26. }
    To copy to clipboard, switch view to plain text mode 

    Function getTitleDescription() as follows:
    Qt Code:
    1. QColor getTitleDescriptionColor(const DM::Object *_pTitle, const QColor &_colorBackground, QGraphicsRectItem *_row)
    2. {
    3.  
    4. QColor ret = _colorBackground;
    5.  
    6. if (CORE::checkPtrType<C2DM::LinkState>(_pTitle) == true)
    7. {
    8.  
    9. C2DM::LinkState *pState = (C2DM::LinkState*)_pTitle;
    10.  
    11. // If the state type passed in does not match the state type stored in the rect, then do nothing
    12. int stateType = int(pState->m_eState);
    13. int rectState = _row->data(0).toInt();
    14. if (stateType != rectState)
    15. {
    16.  
    17. return ret;
    18.  
    19. }
    20. else
    21. {
    22.  
    23. if (pState->m_eState == C2DM::LinkState::EIS_GOOD)
    24. {
    25. ret = QColor(Qt::green).darker(120);
    26. _row->setBrush(ret);
    27. }
    28. else if (pState->m_eState == C2DM::LinkState::EIS_BUSY)
    29. {
    30. ret = QColor(Qt::yellow).darker(120);
    31. _row->setBrush(ret);
    32. }
    33. else
    34. {
    35. ret = QColor(Qt::red).darker(120);
    36. _row->setBrush(ret);
    37. }
    38.  
    39. }
    40.  
    41.  
    42. }
    To copy to clipboard, switch view to plain text mode 

    Please pardon me for slow understanding, please help me on the way forward.Thank you for your help in advance.
    Attached Images Attached Images

  8. #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: QGraphicRectItem update colour in foreach statement

    however when it updates the status correctly it also add new QGraphicsRectItems(see attachment),a repeat of QGraphicsRectItems that was on the scene but with an updated status. I called the addRect function on the update statement like this:
    Think about what you are saying here. If the status of a rect changes, why would you want to add a new rect? Just change the status of the rect that already exists. You can call setData() for a rect any time, not just when you create it. If the status changes from EIS_GOOD to EIS_BUSY, then simply call setData( 0, EIS_BUSY ) for that rect, don't create a new one with EIS_BUSY status.

    You need to take a step back and really think through the logic of your program. It seems like you are just copying and pasting without really thinking about what you want the code to do.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  9. #9
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    I think you misunderstood me. What I meant is I do not want a new rect to be added everytime a status change,how do I this? is my question. setdata() is setup correctly because the color of the rect changes as i expect,But i do not want a new rect to be added with the new status. On my addRect() function, the first thing i do is to create a new rect, then setdata on that rect,like this:

    Qt Code:
    1. void GatewayWidget::addRect(DM::Object *_pTitle)
    2. {
    3.  
    4. QGraphicsTextItem *textColor = scene->addText(QString::fromStdString(pState->m_strLinkId));
    5. QGraphicsRectItem *rectangleColor = new QGraphicsRectItem(QRectF(0, 0, 50, 50), textColor); //create rect
    6. rectangleColor->setData(0, int(pState->m_eState));//then set data
    To copy to clipboard, switch view to plain text mode 

    my question is, is there a way I can setdata() without creating a new rect? how do i call setdata() for an existing rect on the scene?

    Please see the attached image i sent, you can see that setdata is correct but i do not know how to prevent the creation of a new rect

  10. #10
    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: QGraphicRectItem update colour in foreach statement

    is there a way I can setdata() without creating a new rect? how do i call setdata() for an existing rect on the scene?
    Of course you can call setData() on an existing rect.

    I think your basic problem is that you do not have any connection between the data you are trying to model (your data tree of links and nodes) and the graphical items you are using to display the model on the screen (the QGraphicsRectItem and QGraphicsLineItem instances).

    If you want the graphics items on the screen to reflect the status of the data items in your model, then you have to create another data structure that connects a specific item from your model with the graphics item that represents it on screen. This is what I meant several replies ago when I said:

    So what you need to do is to add an association between each rect and its specific LinkState value.
    You can't add items to your graphics scene and then just forget about them. If they represent something in your model, you need to create an explicit association between the model and the graphics item.

    What I would do is create something like this:

    Qt Code:
    1. std::map< DM::Object *, QGraphicsItem * >
    To copy to clipboard, switch view to plain text mode 

    as a data structure in the GatewayWidget class (or some other class if it is more appropriate). Each time you create a new graphics item, you add an entry to the map that associates the Object with the graphics item. When you need to update a graphics item because the Object status has changed, you use the map to retrieve the graphics item pointer using the Object pointer as the key.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  11. #11
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    Hello

    Thank you for your help one again. I used std::map and it updates correctly. I have a problem with the routes(source and destination). I sometimes have multiple source address(string) going to different destinations and I read that with std::map() i cannot have multiple keys. The mapping that worked for the links(unique keys and values) is
    Qt Code:
    1. std::map< std::string, QGraphicsItem * > QgraphicRectItems;//declared in my .h file
    2.  
    3. rectangleColor->setData(0, int(pState->m_eState));
    4. QgraphicRectItems.insert(std::make_pair(pState->m_strLinkId, rectangleColor));//make a pair of QGraphicRect items on the scene and their link IDs
    To copy to clipboard, switch view to plain text mode 

    then on my update function i call the mappings like this:
    Qt Code:
    1. std::map< std::string, QGraphicsItem *>::iterator it = QgraphicRectItems.find(pState->m_strLinkId);
    2. if (it != QgraphicRectItems.end()) {
    3. QGraphicsItem *name = it->second;
    4. name->setData(0, int(pState->m_eState));
    5. QGraphicsRectItem *rect = qgraphicsitem_cast<QGraphicsRectItem *>(name);
    6. getTitleDescriptionColor(pState, m_backgroundColor, rect);
    To copy to clipboard, switch view to plain text mode 

    But for the routes this doesn't work because sometimes i have multiple keys, so I implemented std::multimap like this:
    Qt Code:
    1. std::multimap<std::string, QGraphicsItem *> RouteSourceDuplicates;//declared on my .h file
    2.  
    3. else if (CORE::checkPtrType<C2DM::RouteState>(_pTitle) == true)
    4. {
    5. C2DM::RouteState *pRoute = (C2DM::RouteState*)_pTitle;
    6.  
    7. rectangle = new QGraphicsRectItem(QRectF(0, 0, 60, 60), text);
    8.  
    9. rectangle->setData(0, int(pRoute->m_eTxLinkState));
    10. RouteSourceDuplicates.insert(std::make_pair(pRoute->m_strSource, rectangle));//make a pair of QGraphicRect items on the scene and their source IDs
    To copy to clipboard, switch view to plain text mode 

    then on my calling function i did like this:
    Qt Code:
    1. else if (_eType == QSubscription::UPDATED_TITLES)
    2. {
    3. C2DM::RouteState *pRoute = (C2DM::RouteState*)objPtr->_clone();
    4.  
    5. for (std::multimap<std::string, QGraphicsItem *>::iterator Values = RouteSourceDuplicates.begin();
    6. Values != RouteSourceDuplicates.end(); ++Values)
    7. {
    8.  
    9. QGraphicsItem *nameSource = Values->second;
    10. nameSource->setData(0, int(pRoute->m_eTxLinkState));
    11. QGraphicsRectItem *rectSource = qgraphicsitem_cast<QGraphicsRectItem *>(nameSource);//it breaks on this qgraphicitem_cast
    12.  
    13. getTitleDescriptionColor(pRoute, m_backgroundColor, rectSource);
    14.  
    15. }
    To copy to clipboard, switch view to plain text mode 

    It only works the first time i load the data, second time it just crushes. it gives an Access violation executing location error(please see attachment,it has the error where it breaks). I am struggling to fix it. I am asking for your guidance once again to make it work, please.
    the duplicate keys in my data is like this:

    Qt Code:
    1. pRoute->m_strSource[Node A] pRoute->m_strDestination[Node B] //same source address but different destinations
    2. pRoute->m_strSource[Node A] pRoute->m_strDestination [Node C]
    To copy to clipboard, switch view to plain text mode 
    and I am using pRoute->m_strSource as my key and QgraphicsItem as a value in std::multimap
    Attached Images Attached Images

  12. #12
    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: QGraphicRectItem update colour in foreach statement

    second time it just crushes.
    The error seems to be due to an invalid QGraphicsRectItem pointer. Either you are storing a NULL pointer in your map / multimap or you have deleted a QGraphicsRectItem and you have not updated the map / multimap to remove that pointer. So when qgraphicsitem_cast() tries to access the item (the rect pointer) it is accessing a NULL or invalid pointer and it crashes.

    I still do not understand why you are calling clone() every time you access one of your DM:: Object instances. Why? You don't save these cloned copies anywhere. Just cast the "objPtr" to whatever it should be and use it. Don't clone it, because you are simply wasting time and fragmenting memory by repeatedly creating new instances of things, only to throw them away a few lines later when the pointer goes out of scope at the end of the else if() clause.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  13. #13
    Join Date
    Jan 2020
    Posts
    13
    Qt products
    Qt5
    Platforms
    Windows

    Default Re: QGraphicRectItem update colour in foreach statement

    Thank you for your help once more, its working now, it was an invalid pointer like you said. Concerning the clone() , its the only way I knew how to retrieve the object instances, I am still newbie in this. I am going to try and implement as you advise.Thank you.

    I got another question please if I am still allowed. The nodes(QGraphicsRectItems) in the scene keeps crossing paths. I know I am supposed to set the setPos() for each of the nodes on the scene but I do not how to store the items so that I can set individual setPos(). I read my data from the object instance like this:

    Qt Code:
    1. void GatewayWidget::addRect(DM::Object *_pTitle)
    2. {
    3.  
    4. C2DM::RouteState *pRoute = (C2DM::RouteState*)_pTitle;
    5. QGraphicsRectItem *rectangle;
    6.  
    7. text = scene->addText(QString::fromStdString(pRoute->m_strSource));// pRoute->Source may contain 4, 8 or any number of nodes that are retried from the data
    8. text->setPos(600, (qrand() % 400)); //try to setpos() but its ugly
    9. rectangle = new QGraphicsRectItem(QRectF(0, 0, 60, 60), text); //then put it in QGraphicsRectItems
    To copy to clipboard, switch view to plain text mode 

    I tried to set randomly position them, which is not ideal. Now this makes the QGraphicsLineItems *line that I use to connect source and destination to cross paths(please see attachment). So I am asking for your guidance, on how I can store the nodes(pRoute->Source) ,which will enable me to retrieve and setPos() for each QGraphicRectItem?
    Attached Images Attached Images

  14. #14
    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: QGraphicRectItem update colour in foreach statement

    how I can store the nodes
    I think you need to do some research online. Start by using Google for "directed graph c++" and read about the different ways to implement graph data structures. (Your DM Object trees and the matching QGraphicsItem tree) are directed graphs in computer science / mathematics terminology.

    Next you need to use Google to find information on "directed graph layout". There are many ways to lay out graphs, but this Wikipedia article on "Layered graph drawing" might be good for your needs. To draw a layered graph, you create a "row" for each level in your tree. You then count the number of nodes at each level, and the divide the row up into that many boxes and put one node in each box, under the parent it belongs to. You can see an example on the Wikipedia page.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

Similar Threads

  1. foreach or alike
    By prophet0 in forum Qt Programming
    Replies: 18
    Last Post: 5th January 2012, 18:03
  2. foreach error while compiling
    By smanoj in forum Newbie
    Replies: 4
    Last Post: 24th November 2011, 06:32
  3. Help with QT, SQLite, Update Statement
    By chetu1984 in forum Newbie
    Replies: 3
    Last Post: 17th March 2011, 23:24
  4. lifetime of foreach
    By BalaQT in forum Newbie
    Replies: 4
    Last Post: 4th March 2010, 16:55
  5. Foreach performance
    By jano_alex_es in forum General Programming
    Replies: 2
    Last Post: 17th November 2009, 14:26

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.