Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Faster way to find a QRectItem in a QGraphicsScene
Forum Updated to NodeBB v4.3 + New Features

Faster way to find a QRectItem in a QGraphicsScene

Scheduled Pinned Locked Moved Unsolved General and Desktop
8 Posts 3 Posters 707 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • L Offline
    L Offline
    leinad
    wrote on last edited by
    #1

    Hi,
    I have a method which I'm trying to get a rectItem from a scene so I can set its color. Essentially it is a grid of squares which could be thousands of them and I have to set certain cells to a specific color. The problem is when I iterate through all the cells the main event loop hangs trying to do the processing. I can't color the cells in another thread as that is not the proper way to do it plus it can cause a crash.
    My code looks like this, is there a way I can optimize the search so it doesn't take so long? 10,000 cells can take about a minute or so and I can have many more cells. The grid is always symmetrical like a chess board. The number of rows always equals the number of columns. Any help would be appreciated.

    colorCells(int column, int row, QString failureColor)
    {
    QString text = NULL;

    QList<QGraphicsItem*> itemList = scene_->items();
    for (int i = 0; i < itemList.size(); i++)
    {
        // find the global (screen) position of the item
        if (auto lineItem{ dynamic_cast<CustomRectItem*>(itemList[i]) })
        {
          //this takes a long time!!
            QPointF sceneP = itemList.at(i)->mapToScene(itemList[i]->boundingRect().topLeft());
            int globalColumn = ((static_cast<int>(sceneP.x() - sceneStartCornerX_) / CELL_SIZE)) + 2;
            int globalRow = ((static_cast<int>(sceneP.y() - sceneStartCornerY_) / CELL_SIZE)) + 2;
    
            if (column == globalColumn && row == globalRow)
            {
                if (failureColor.compare("red") == 0)
                {
                    lineItem->setBrush(Qt::red);  //turn the cell red
                }
                else if(failureColor.compare("white") == 0)//no failure
                {
                    if(globalColumn == globalRow)
                        lineItem->setBrush(Qt::lightGray); //no failure so light grey if diagnal cell
                    else
                        lineItem->setBrush(Qt::white); //no failure so no color
                }
                else //yellow
                    lineItem->setBrush(Qt::yellow);  //turn the cell red
    
                return;
            }
        }
    }
    

    }

    JonBJ 1 Reply Last reply
    0
    • L leinad

      Hi,
      I have a method which I'm trying to get a rectItem from a scene so I can set its color. Essentially it is a grid of squares which could be thousands of them and I have to set certain cells to a specific color. The problem is when I iterate through all the cells the main event loop hangs trying to do the processing. I can't color the cells in another thread as that is not the proper way to do it plus it can cause a crash.
      My code looks like this, is there a way I can optimize the search so it doesn't take so long? 10,000 cells can take about a minute or so and I can have many more cells. The grid is always symmetrical like a chess board. The number of rows always equals the number of columns. Any help would be appreciated.

      colorCells(int column, int row, QString failureColor)
      {
      QString text = NULL;

      QList<QGraphicsItem*> itemList = scene_->items();
      for (int i = 0; i < itemList.size(); i++)
      {
          // find the global (screen) position of the item
          if (auto lineItem{ dynamic_cast<CustomRectItem*>(itemList[i]) })
          {
            //this takes a long time!!
              QPointF sceneP = itemList.at(i)->mapToScene(itemList[i]->boundingRect().topLeft());
              int globalColumn = ((static_cast<int>(sceneP.x() - sceneStartCornerX_) / CELL_SIZE)) + 2;
              int globalRow = ((static_cast<int>(sceneP.y() - sceneStartCornerY_) / CELL_SIZE)) + 2;
      
              if (column == globalColumn && row == globalRow)
              {
                  if (failureColor.compare("red") == 0)
                  {
                      lineItem->setBrush(Qt::red);  //turn the cell red
                  }
                  else if(failureColor.compare("white") == 0)//no failure
                  {
                      if(globalColumn == globalRow)
                          lineItem->setBrush(Qt::lightGray); //no failure so light grey if diagnal cell
                      else
                          lineItem->setBrush(Qt::white); //no failure so no color
                  }
                  else //yellow
                      lineItem->setBrush(Qt::yellow);  //turn the cell red
      
                  return;
              }
          }
      }
      

      }

      JonBJ Offline
      JonBJ Offline
      JonB
      wrote on last edited by JonB
      #2

      @leinad
      Trying to understand your code.....

      You have some constant globalColumn & globalRow variables? You want to find which of your CustomRectItem items in the scene intersect that point? Map your coordinates to scene coordinates and use QGraphicsScene::itemAt() or quite possibly one of the QGraphicsScene::items() overloads which takes a QRectF to find any gfx items intersecting a rectangular area, whatever is appropriate to your requirement. The docs include

      QGraphicsScene uses an indexing algorithm to manage the location of items efficiently.
      One of QGraphicsScene's greatest strengths is its ability to efficiently determine the location of items. Even with millions of items on the scene, the items() functions can determine the location of an item within a few milliseconds.

      Basically, you seem to be iterating every gfx item to see if it's in the desired place. Change that to ask QGraphicsScene what item(s) are at the desired place, as above, it can do that very fast without looking through all the items.

      L 1 Reply Last reply
      0
      • JonBJ JonB

        @leinad
        Trying to understand your code.....

        You have some constant globalColumn & globalRow variables? You want to find which of your CustomRectItem items in the scene intersect that point? Map your coordinates to scene coordinates and use QGraphicsScene::itemAt() or quite possibly one of the QGraphicsScene::items() overloads which takes a QRectF to find any gfx items intersecting a rectangular area, whatever is appropriate to your requirement. The docs include

        QGraphicsScene uses an indexing algorithm to manage the location of items efficiently.
        One of QGraphicsScene's greatest strengths is its ability to efficiently determine the location of items. Even with millions of items on the scene, the items() functions can determine the location of an item within a few milliseconds.

        Basically, you seem to be iterating every gfx item to see if it's in the desired place. Change that to ask QGraphicsScene what item(s) are at the desired place, as above, it can do that very fast without looking through all the items.

        L Offline
        L Offline
        leinad
        wrote on last edited by
        #3

        @JonB Thanks but how can I find a specific rect corresponding to it column/row location? Can you provide a simple example? I pass the row column, I need to know that cell item so I can color it.

        JonBJ 1 Reply Last reply
        0
        • L leinad

          @JonB Thanks but how can I find a specific rect corresponding to it column/row location? Can you provide a simple example? I pass the row column, I need to know that cell item so I can color it.

          JonBJ Offline
          JonBJ Offline
          JonB
          wrote on last edited by
          #4

          @leinad said in Faster way to find a QRectItem in a QGraphicsScene:

          Thanks but how can I find a specific rect corresponding to it column/row location?

          Only you know that. Row/column location in what sense? If it's a "grid of squares", multiply them to find the corresponding rectangle in scene coordinates then search for the items intersecting that rectangle?

          1 Reply Last reply
          0
          • L Offline
            L Offline
            leinad
            wrote on last edited by
            #5

            Sorry but I'm not sure what you mean multiply them?

            I pass in (column, row)
            I now have QList<QGraphicsItem*> itemList = scene_->items();
            how to I find itemList.at(i) using column and row? Column and row is 2 dimensional. QList is one dimensional.
            Do you mean itemList.at(column *row)?

            JonBJ M 2 Replies Last reply
            0
            • L leinad

              Sorry but I'm not sure what you mean multiply them?

              I pass in (column, row)
              I now have QList<QGraphicsItem*> itemList = scene_->items();
              how to I find itemList.at(i) using column and row? Column and row is 2 dimensional. QList is one dimensional.
              Do you mean itemList.at(column *row)?

              JonBJ Offline
              JonBJ Offline
              JonB
              wrote on last edited by JonB
              #6

              @leinad
              I explained. Multiply your row, column as necessary to change it into GraphicsScene coordinates (a pair of values, like row,column, not one single number). You now have the top-left of the square in gfx coords, and you know the size of a square in gfx coordinates too. Depending on your requirements, if you only need to look at the top-left coord to locate a QGraphicsItem (i.e. you always place them at the top-left of a square), you can use itemAt() to determine which gfx item, if any, is there. If you need to look at the whole gfx coords square to see which gfx item(s) it intersects, use the appropriate QGraphicsScene::items() overload which looks for a QRectF area.

              1 Reply Last reply
              0
              • L leinad

                Sorry but I'm not sure what you mean multiply them?

                I pass in (column, row)
                I now have QList<QGraphicsItem*> itemList = scene_->items();
                how to I find itemList.at(i) using column and row? Column and row is 2 dimensional. QList is one dimensional.
                Do you mean itemList.at(column *row)?

                M Offline
                M Offline
                mchinand
                wrote on last edited by
                #7

                @leinad said in Faster way to find a QRectItem in a QGraphicsScene:

                how to I find itemList.at(i) using column and row? Column and row is 2 dimensional. QList is one dimensional.

                As @JonB mentioned, use one of the QGraphicsScene::items() overloads that takes a scene position or scene Rect.

                1 Reply Last reply
                0
                • L Offline
                  L Offline
                  leinad
                  wrote on last edited by
                  #8

                  Ok, thanks. I'll take a look

                  1 Reply Last reply
                  0

                  • Login

                  • Login or register to search.
                  • First post
                    Last post
                  0
                  • Categories
                  • Recent
                  • Tags
                  • Popular
                  • Users
                  • Groups
                  • Search
                  • Get Qt Extensions
                  • Unsolved