Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Error using foreach



  • I'm having a problem using the foreach an I don't know why I am wrong

    If i do something like this, it works just fine

    foreach(QGraphicsItem *item,scene->items()){
    

    But if I do something like this(Remembering that QGrphicsItem is parent of Diagram Item):

    foreach(DiagramItem *itempos,scene->items()){
    

    it gives me the following error

    mainwindow.cpp:166:40: error: cannot initialize a variable of type 'DiagramItem *' with an lvalue of type 'QGraphicsItem *const'
    qglobal.h:1029:21: note: expanded from macro 'foreach'
    qglobal.h:1021:10: note: expanded from macro 'Q_FOREACH'

    how can i fix it?


  • Lifetime Qt Champion

    Hi,

    Is DiagramItem a subclass of QGraphicsItem ?
    If so, then just cast the pointer to it in the loop.



  • Hi,

    yes it is!

    Now i think what is the problem

    foreach(QGraphicsItem *item,scene->items()){
    

    i defined scene as DiagramScene *scene, and when i do scene->items it returns a QGraphicsItem :( i don't know if i can fix it



  • is there someway to tell to the computer that the object is member of a subclass too?
    like scene->item is for sure a QGraphicsItem, but is also a DiagramItem that is a subclass of DiagramItem

    i don't know if i was clear


  • Lifetime Qt Champion

    As already suggested, just cast it in the loop. Otherwise you have to add your own method to your class that returns that list of your subclass.



  • how can i do this?

    sorry, i don't what it is


  • Lifetime Qt Champion

    @frnklu20

    Could be something like this:

    foreach(QGraphicsItem *item,scene->items()){
        DiagramItem *itempos = (DiagramItem *)item;
        ...
    }
    

    Regards



  • oh thanks :))


  • Lifetime Qt Champion

    You also have qgraphicsitem_cast. Take a look at the documentation. There's on additional thing you have to do before using it.



  •                           if(item->type()==DiagramItem::Type && itempos->type()==DiagramItem::Type
                                      && itempos!=item){
                              DiagramItem *itempos = (DiagramItem *)item;
                              DiagramItem *item = (DiagramItem *)item;
    
                              DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(item);
                              DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(itempos);
                              Arrow *arrow = new Arrow(startItem, endItem);
                              arrow->setColor(scene->myLineColor);
                              item->addArrow(arrow);
                              itempos->addArrow(arrow);
                              arrow->setZValue(-1000.0);
                              scene->addItem(arrow);
                              }
    

    like this? the program keep crashing when i do this


  • Lifetime Qt Champion

    You're not checking whether these pointers are nullptr.



  •            if(item->type()==DiagramItem::Type && itempos->type()==DiagramItem::Type
                     && itempos!=item && item!=nullptr && itempos!=nullptr){
    

    like this? the program still crashes

    but if i remove the lines:

                 item->addArrow(arrow);
                 itempos->addArrow(arrow);
    

    it doesn't crashes but it doesn't draw a line between the objects neither


  • Lifetime Qt Champion

    @frnklu20 Where does it crash exactly? Use a debugger and step through to find the faulty line.



  • what i'm trying to do is drawing a line that is QGraphicsItem between 2 objects that already exist using the DiagramScene example form Qt

    diagramscene.cpp

    void DiagramScene::mousePressEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
           
        if (mouseEvent->button() != Qt::LeftButton)
            return;
    
        DiagramItem *item;
        switch (myMode) {
               case InsertLine:
                line = new QGraphicsLineItem(QLineF(mouseEvent->scenePos(),
                                            mouseEvent->scenePos()));
                line->setPen(QPen(myLineColor, 2));
                addItem(line);
                break;
    }
    }
    
    void DiagramScene::mouseMoveEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        if (myMode == InsertLine && line != 0) {
            QLineF newLine(line->line().p1(), mouseEvent->scenePos());
            line->setLine(newLine);
        } else if (myMode == MoveItem) {
            QGraphicsScene::mouseMoveEvent(mouseEvent);
        }
    }
    
    void DiagramScene::mouseReleaseEvent(QGraphicsSceneMouseEvent *mouseEvent)
    {
        if (line != 0 && myMode == InsertLine) {
            QList<QGraphicsItem *> startItems = items(line->line().p1());
            if (startItems.count() && startItems.first() == line)
                startItems.removeFirst();
            QList<QGraphicsItem *> endItems = items(line->line().p2());
            if (endItems.count() && endItems.first() == line)
                endItems.removeFirst();
    
            removeItem(line);
            delete line;
    
    
            if (startItems.count() > 0 && endItems.count() > 0 &&
                startItems.first()->type() == DiagramItem::Type &&
                endItems.first()->type() == DiagramItem::Type &&
                startItems.first() != endItems.first()) {
                DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(startItems.first());
                DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(endItems.first());
                Arrow *arrow = new Arrow(startItem, endItem);
                arrow->setColor(myLineColor);
                startItem->addArrow(arrow);
                endItem->addArrow(arrow);
                arrow->setZValue(-1000.0);
                addItem(arrow);  #and here it draws the line
                arrow->updatePosition()
    }
    }
    

    and i what i want to draw a line between 2 objects but not by creating a line with insertline mode

    mainwindow.cpp

    void MainWindow::infoItem()
    {
        foreach (QGraphicsItem *item, scene->selectedItems()){#the item object is the selected one
           if (item->type() == DiagramItem::Type){
    
    if(item->data(0)=="Carga"){#carga is type of object
    CargaDialog *carga=new CargaDialog;
                  carga->setModal(true);
    #its a dialog that contains a combo box, an the items of this combo box are the items that are in the screen that are not cargas
    #and after select an item in the combo box, it will draw a line between the carga and the item selected
    
    if(carga->getItem()!="Selecione um barramento" && carga->getItem()!=(item->data(1)).toString()){
                      #getItem() is a function that return the name of item selected in the combo box
                      item->setData(4,carga->getItem());
                      foreach(QGraphicsItem *itempos,scene->items()){
                          if(itempos->data(1)==carga->getItem())
                         #i use the data(1) slot of the objects to store the name of each object, so now i looking for the QGraphicsItem that have the same name as the item selected
                          {
    
                              if(item->type()==DiagramItem::Type && itempos->type()==DiagramItem::Type
                                      && itempos!=item && item!=nullptr && itempos!=nullptr){
                              DiagramItem *itempos = (DiagramItem *)item;
                              DiagramItem *item = (DiagramItem *)item;
    
                              DiagramItem *startItem = qgraphicsitem_cast<DiagramItem *>(item);
                              DiagramItem *endItem = qgraphicsitem_cast<DiagramItem *>(itempos);
                              Arrow *arrow = new Arrow(startItem, endItem);
                              arrow->setColor(scene->myLineColor);
                              item->addArrow(arrow);#if i remove these two lines, the program doesn't crash but it doesn't draw a line on the screen
                              itempos->addArrow(arrow);
                              arrow->setZValue(-1000.0);
                              scene->addItem(arrow);
                              arrow->updatePosition();
                              }
                          }
    

    i don't know why this is going on, because it's exactaly the same this that is done in diagramscene.cpp


  • Lifetime Qt Champion

    As already suggested, start your application with the debugger and check the stack trace.



  • @frnklu20 said in Error using foreach:

    (DiagramItem *)item;

    Should this be done this way?

    DiagramItem *itempos = dynamic_cast<DiagramItem*>(item);
    // check if itempos is null
    

    This gives us some more type safety no?


Log in to reply