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. Why is QTreeView highlighting wrong row (different than selection)
Forum Updated to NodeBB v4.3 + New Features

Why is QTreeView highlighting wrong row (different than selection)

Scheduled Pinned Locked Moved Solved General and Desktop
18 Posts 5 Posters 4.6k Views 4 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.
  • michalosM Offline
    michalosM Offline
    michalos
    wrote on last edited by michalos
    #1

    Hi,
    Does any one know how is it posible, that when I hover over a item in my tree view, Qt thinks, I'm hovering over a different one?
    It's always correct about the item on the top of visible part of the list(tree view without indentation), but every other is like ++ (when I select the second, the blue rectangle is on the third; when I select the third, its on the fifth; its on the ninth).
    I have a custom delegate and QTreeView, but I did not touch the model index in any way.
    I'm using Qt 5.71 with MSVC 2015 64bit

    Any idea where I should look for bugs?

    Below are two examples of my widget

    two examples of my widget

    mouse was howering over the row where the two buttons (rectangles) are

    1 Reply Last reply
    0
    • mrjjM Offline
      mrjjM Offline
      mrjj
      Lifetime Qt Champion
      wrote on last edited by mrjj
      #2

      Hi
      Without code its just random guessing but it does work sometimes :)
      The distance from the Hover target to the wrong blue seems to be directly
      the same as from top to the hover target. In both cases.

      This makes we wonder if you use x,y of mouse event for anything and either call
      mapFromGlobal or not before using them or that the x,y is already convert to client space but its
      the wrong client. Kinda situation. Like the TreeView has a viewport etc.

      Sp do you have any code related to hover event and selecting an item?

      1 Reply Last reply
      1
      • michalosM Offline
        michalosM Offline
        michalos
        wrote on last edited by michalos
        #3

        Thank You for Your answer mrjj.
        I have this related to mouse hover:

        MyTreeView::MyTreeView(QWidget *parent) : QTreeView(parent)
        {
            setMouseTracking(true);
        }
        
        void MyTreeView::mouseMoveEvent(QMouseEvent *event){
            mousePressEvent(event);
        }
        
        void MyTreeView::leaveEvent(QEvent *event)
        {
        //    setMouseTracking(false);
            qDebug() << "left treeView";
        
            emit saveToModelFromEditor();
        
            QTreeView::leaveEvent(event);
        }
        
        void MyTreeView::resizeEvent(QResizeEvent *e)
        {
            if(model() != Q_NULLPTR){
                model()->layoutChanged();
            }
            QTreeView::resizeEvent(e);
        }
        

        and in main window:

        void MainWindow::mouseMoveEvent(QMouseEvent *event)
        {
            {
                if (event->buttons() & Qt::LeftButton)
                {
                    move(event->globalPos() - dragPosition);
                    event->accept();
                }
            }
            QWidget::mouseMoveEvent(event);
        }
        
        1 Reply Last reply
        0
        • mrjjM Offline
          mrjjM Offline
          mrjj
          Lifetime Qt Champion
          wrote on last edited by mrjj
          #4

          Hi
          Just note first
          void MyTreeView::mouseMoveEvent(QMouseEvent *event){
          mousePressEvent(event);
          }

          why are you calling mousePressEvent when you move the mouse?

          I dont spot any code that should give this offset.

          you dont use enterEvent ?

          1 Reply Last reply
          1
          • michalosM Offline
            michalosM Offline
            michalos
            wrote on last edited by michalos
            #5

            I use it to select a row for editing.
            So that when I hover the mouse over a row the editor is trigered.
            I need it, because I have a view, that needs to handle over 10 000 rows.
            When I draw editors for every item at once the UI slows down drasticaly.

            void MainWindow::setupTreeView()
            {
                itemDelegate = new MyItemDelegate(this);
                treeView->setItemDelegate(itemDelegate);
                treeView->header()->hide();
                treeView->setIndentation(0);
                treeView->setModel(aModel);
                treeView->setSelectionMode(QAbstractItemView::SingleSelection);  // this line here
                treeView->setEditTriggers(QAbstractItemView::CurrentChanged);  // and this line here
                treeView->expandAll();
            }
            

            Do You have any other solution?

            mrjjM 1 Reply Last reply
            0
            • michalosM michalos

              I use it to select a row for editing.
              So that when I hover the mouse over a row the editor is trigered.
              I need it, because I have a view, that needs to handle over 10 000 rows.
              When I draw editors for every item at once the UI slows down drasticaly.

              void MainWindow::setupTreeView()
              {
                  itemDelegate = new MyItemDelegate(this);
                  treeView->setItemDelegate(itemDelegate);
                  treeView->header()->hide();
                  treeView->setIndentation(0);
                  treeView->setModel(aModel);
                  treeView->setSelectionMode(QAbstractItemView::SingleSelection);  // this line here
                  treeView->setEditTriggers(QAbstractItemView::CurrentChanged);  // and this line here
                  treeView->expandAll();
              }
              

              Do You have any other solution?

              mrjjM Offline
              mrjjM Offline
              mrjj
              Lifetime Qt Champion
              wrote on last edited by
              #6

              @michalos
              I think the offset might come from this passing of event variable from move to press.
              Must be tested to know if its that.

              I was expecting something like
              EnterEvent()
              Find item under x,y via itemAt and then treeView->setCurrentIndex to select it.

              Nothing wrong with your way but i think the offset comes from selecting it this way but
              only test can tell.

              1 Reply Last reply
              1
              • michalosM Offline
                michalosM Offline
                michalos
                wrote on last edited by michalos
                #7

                I've commented out mose related events in my View, and then in mainwindow.
                The behaviour is the same, only now I need to click for it to occur.

                Funny thing is, that it was working about two weeks ago.

                Is it posible, that the latest Qt update (5.71) did it?

                mrjjM 1 Reply Last reply
                0
                • michalosM michalos

                  I've commented out mose related events in my View, and then in mainwindow.
                  The behaviour is the same, only now I need to click for it to occur.

                  Funny thing is, that it was working about two weeks ago.

                  Is it posible, that the latest Qt update (5.71) did it?

                  mrjjM Offline
                  mrjjM Offline
                  mrjj
                  Lifetime Qt Champion
                  wrote on last edited by
                  #8

                  @michalos
                  Well if it used to work then its possible the update did something.

                  Just so im sure I test the right thing.
                  When you hover an item, it should be selected and put into edit mode?

                  1 Reply Last reply
                  0
                  • michalosM Offline
                    michalosM Offline
                    michalos
                    wrote on last edited by michalos
                    #9

                    Yes.
                    When I hover over an item in the View, the styledItemDelegate is called and depending on one of the item userRole's the correct editor is selected.

                    It's the same in Qt 5.6_2

                    I don't have acces to older versions right now.

                    I setup my model from an SQLite query, like this:

                    
                        rootNode = model->invisibleRootItem();
                        groupNameItem = Q_NULLPTR;
                        contactItem = Q_NULLPTR;
                    
                        groupId = 0;
                        contactId = 0;
                        phoneNo = 0;
                        phoneRole = 100;
                    
                        /////////////////////////////////////////////////// setup model dla wszystkich kontaktów
                        queryHasAnswer = false;
                    
                        groupNameItem = new QStandardItem("DelleteThisInMainwindow"); //group_names.name
                        groupNameItem->setData(0,Qt::UserRole);  //group_names.id
                        groupNameItem->setData(0,Qt::UserRole+1);  //group_names.favorite
                        groupNameItem->setData(1,Qt::UserRole+9);
                        while (query.next()) {
                        queryHasAnswer = true;
                    
                    
                        if (contactId != query.value(0))  {
                            if(contactItem != Q_NULLPTR){
                                groupNameItem->appendRow(contactItem);
                                contactItem = Q_NULLPTR; //niepowinno być potrzebne
                            }
                            phoneRole = 100;
                            contactId = query.value(0);
                            contactItem = new QStandardItem(query.value(1).toString()); //contact name
                            contactItem->setData(contactId, Qt::UserRole); //contact id
                            contactItem->setData(query.value(2), Qt::UserRole+1);  //extNo
                            contactItem->setData(query.value(3), Qt::UserRole+2);   //favorite
                            contactItem->setData(2, Qt::UserRole+9); // determinuje, że Contacts - dla itemDelegate::paint
                            phoneNo = query.value(4);  //numer telefonu do kontaktu
                            contactItem->setData(phoneNo, Qt::UserRole+phoneRole++);    //phone number
                        } else if (contactItem != Q_NULLPTR) {
                            phoneNo = query.value(4);  //numer telefonu do kontaktu
                            contactItem->setData(phoneNo, Qt::UserRole+phoneRole++);    //phone number
                        }
                    
                        } //while(query.next())
                    
                        if(queryHasAnswer){
                        groupNameItem->appendRow(contactItem); //ostatni z contacts
                        rootNode->appendRow(groupNameItem); //ostatni z group_names
                        }
                    
                    1 Reply Last reply
                    0
                    • mrjjM Offline
                      mrjjM Offline
                      mrjj
                      Lifetime Qt Champion
                      wrote on last edited by mrjj
                      #10

                      Ok. seems fine. I dont think its related to the data as such.
                      Just seems to be confused about Y from mouse Event.
                      But i am just guessing. only debugger will know :)

                      Update:
                      Hmm. I made small sample with TreeView and called MouseDown from MouseMove
                      but i dont get any offset-ish effect. All you move over is just in edit mode.

                      https://www.dropbox.com/s/9ee7171vcam12re/myhover.zip?dl=0

                      So i guess its something else. Just to be be sure. can u run sample.

                      Do you have a smaller sample that has this issue ?

                      1 Reply Last reply
                      2
                      • VRoninV Offline
                        VRoninV Offline
                        VRonin
                        wrote on last edited by
                        #11

                        in your delegate, do you reimplement updateEditorGeometry? if so, could you post the code?

                        "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                        ~Napoleon Bonaparte

                        On a crusade to banish setIndexWidget() from the holy land of Qt

                        1 Reply Last reply
                        1
                        • michalosM Offline
                          michalosM Offline
                          michalos
                          wrote on last edited by
                          #12

                          There it is:

                          void MyItemDelegate::updateEditorGeometry(QWidget *editor, const QStyleOptionViewItem &option, const QModelIndex &index) const
                          {
                              editor->setGeometry(option.rect);
                          }
                          
                          1 Reply Last reply
                          0
                          • michalosM Offline
                            michalosM Offline
                            michalos
                            wrote on last edited by michalos
                            #13

                            I've found, that there is no problem for the parent, only for the children.
                            The parrent has no highlight at all.

                            Also without seting my delegate to the treeView [treeView->setItemDelegate(itemDelegate) ] the selection works fine.

                            It would suggest that I might messed something up.. but I do not now what could cause such behaviour.

                            Here is the code:

                                   QStyleOptionViewItem options = option;
                                    initStyleOption(&options, index);
                            
                                    painter->save();
                            
                                    int scrollBarrWidth = options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
                            
                                    QRect rectLeft(0,0,26,26);
                                    QRect rectCenter(30,0,(options.rect.right()-40-scrollBarrWidth),26); 
                                    QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26);
                                    QRect boundingRect;
                            
                                    QString nameText(index.data(Qt::DisplayRole).toString());
                                    QString extNoText(index.data(Qt::UserRole+1).toString());
                                    QString phoneText(index.data(Qt::UserRole+100).toString());
                            
                                    painter->translate(options.rect.left(), options.rect.top());
                            
                                    painter->drawPixmap(rectLeft.adjusted(4,4,-4,-4),icoGreenPhone); 
                                    painter->drawPixmap(rectRight.adjusted(4,4,-4,-4), icoMessage); 
                                    painter->setFont(QFont("Segoe UI",9,50));
                                            QTextDocument textDoc;
                                            textDoc.setTextWidth(rectCenter.width());
                            
                                            QTextCursor textCursor(&textDoc);
                                            QString wholeText("");
                            
                                            bool wczytajfote = !stanPoint.isNull();
                            
                                            wholeText.append("<b>");
                                            wholeText.append(nameText);
                                            wholeText.append("</b>");
                                            textCursor.insertHtml(wholeText);
                                            if(wczytajfote){
                                                textCursor.insertHtml("&nbsp");
                                            textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
                                            textCursor.insertImage(stanPoint);
                                            textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
                                            textCursor.insertHtml("&nbsp");
                                            }
                                            wholeText.clear();
                                            if(!extNoText.isEmpty()){
                            
                                                wholeText.append("<font color = blue>");
                                                wholeText.append(QString(" ("+extNoText+") "));
                                                wholeText.append("</font><br><i>");
                                                wholeText.append("infoStr trzeba dostarczyć z tagu Status, a nie z bazy danych");
                                                wholeText.append("</i>");
                                            } else {
                                                wholeText.append("<font color = blue>");
                                                wholeText.append("<br>");
                                                wholeText.append(QString(" ("+phoneText+") "));
                                            }
                                            textCursor.insertHtml(wholeText);
                            
                                            options.text = "";
                                            options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
                                            painter->translate(rectCenter.left(), rectCenter.top());
                            
                                            QRect clip(0,0,textDoc.size().width(), textDoc.size().height());
                                            textDoc.drawContents(painter, clip);
                            
                                    painter->restore();
                            

                            edit: I've left only the paint method

                            VRoninV 1 Reply Last reply
                            0
                            • michalosM michalos

                              I've found, that there is no problem for the parent, only for the children.
                              The parrent has no highlight at all.

                              Also without seting my delegate to the treeView [treeView->setItemDelegate(itemDelegate) ] the selection works fine.

                              It would suggest that I might messed something up.. but I do not now what could cause such behaviour.

                              Here is the code:

                                     QStyleOptionViewItem options = option;
                                      initStyleOption(&options, index);
                              
                                      painter->save();
                              
                                      int scrollBarrWidth = options.widget->style()->pixelMetric(QStyle::PM_ScrollBarExtent);
                              
                                      QRect rectLeft(0,0,26,26);
                                      QRect rectCenter(30,0,(options.rect.right()-40-scrollBarrWidth),26); 
                                      QRect rectRight((options.widget->rect().right()-30-scrollBarrWidth),0,26,26);
                                      QRect boundingRect;
                              
                                      QString nameText(index.data(Qt::DisplayRole).toString());
                                      QString extNoText(index.data(Qt::UserRole+1).toString());
                                      QString phoneText(index.data(Qt::UserRole+100).toString());
                              
                                      painter->translate(options.rect.left(), options.rect.top());
                              
                                      painter->drawPixmap(rectLeft.adjusted(4,4,-4,-4),icoGreenPhone); 
                                      painter->drawPixmap(rectRight.adjusted(4,4,-4,-4), icoMessage); 
                                      painter->setFont(QFont("Segoe UI",9,50));
                                              QTextDocument textDoc;
                                              textDoc.setTextWidth(rectCenter.width());
                              
                                              QTextCursor textCursor(&textDoc);
                                              QString wholeText("");
                              
                                              bool wczytajfote = !stanPoint.isNull();
                              
                                              wholeText.append("<b>");
                                              wholeText.append(nameText);
                                              wholeText.append("</b>");
                                              textCursor.insertHtml(wholeText);
                                              if(wczytajfote){
                                                  textCursor.insertHtml("&nbsp");
                                              textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor);
                                              textCursor.insertImage(stanPoint);
                                              textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor);
                                              textCursor.insertHtml("&nbsp");
                                              }
                                              wholeText.clear();
                                              if(!extNoText.isEmpty()){
                              
                                                  wholeText.append("<font color = blue>");
                                                  wholeText.append(QString(" ("+extNoText+") "));
                                                  wholeText.append("</font><br><i>");
                                                  wholeText.append("infoStr trzeba dostarczyć z tagu Status, a nie z bazy danych");
                                                  wholeText.append("</i>");
                                              } else {
                                                  wholeText.append("<font color = blue>");
                                                  wholeText.append("<br>");
                                                  wholeText.append(QString(" ("+phoneText+") "));
                                              }
                                              textCursor.insertHtml(wholeText);
                              
                                              options.text = "";
                                              options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
                                              painter->translate(rectCenter.left(), rectCenter.top());
                              
                                              QRect clip(0,0,textDoc.size().width(), textDoc.size().height());
                                              textDoc.drawContents(painter, clip);
                              
                                      painter->restore();
                              

                              edit: I've left only the paint method

                              VRoninV Offline
                              VRoninV Offline
                              VRonin
                              wrote on last edited by
                              #14

                              delete all the contents of the destructor, the widgets inside are managed by the parent-child system, don't delete them manually.

                              The code is quite complex so I'd suggest narrowing it down to 1 function. comment the reimplemented methods out then uncomment them back and see if it still works, when it doesn't you found the method responsible

                              "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
                              ~Napoleon Bonaparte

                              On a crusade to banish setIndexWidget() from the holy land of Qt

                              1 Reply Last reply
                              2
                              • michalosM Offline
                                michalosM Offline
                                michalos
                                wrote on last edited by michalos
                                #15

                                The problem is with the MyItemDelegate::paint method.

                                I've found out that commenting out the line, that translates the painters coordinates fixes the highlighting problem.

                                 painter->translate(options.rect.left(), options.rect.top());
                                

                                The question I do not have the answer to is why...
                                Why is this line Ok, when I use a different, similar paint method, and not in this method?

                                Anyone has a clue?

                                edit:
                                I got over the problem by removing the highlight rectangle. I do not need it, so the problem is solved.
                                But I still would be grateful for an answer why the error occurred.

                                  //I've commented out
                                   options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
                                
                                A 1 Reply Last reply
                                0
                                • michalosM michalos

                                  The problem is with the MyItemDelegate::paint method.

                                  I've found out that commenting out the line, that translates the painters coordinates fixes the highlighting problem.

                                   painter->translate(options.rect.left(), options.rect.top());
                                  

                                  The question I do not have the answer to is why...
                                  Why is this line Ok, when I use a different, similar paint method, and not in this method?

                                  Anyone has a clue?

                                  edit:
                                  I got over the problem by removing the highlight rectangle. I do not need it, so the problem is solved.
                                  But I still would be grateful for an answer why the error occurred.

                                    //I've commented out
                                     options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
                                  
                                  A Offline
                                  A Offline
                                  ambershark
                                  wrote on last edited by
                                  #16

                                  @michalos said in Why is QTreeView highlighting wrong row (different than selection):

                                  The problem is with the MyItemDelegate::paint method.

                                  I've found out that commenting out the line, that translates the painters coordinates fixes the highlighting problem.

                                   painter->translate(options.rect.left(), options.rect.top());
                                  

                                  The question I do not have the answer to is why...
                                  Why is this line Ok, when I use a different, similar paint method, and not in this method?

                                  Anyone has a clue?

                                  edit:
                                  I got over the problem by removing the highlight rectangle. I do not need it, so the problem is solved.
                                  But I still would be grateful for an answer why the error occurred.

                                    //I've commented out
                                     options.widget->style()->drawControl(QStyle::CE_ItemViewItem, &options, painter);
                                  

                                  It looks to me like your translate rectangles are wrong. I would check in a debugger or with qDebug() to see why they are so off compared to the actual location of the item.

                                  Usually when this stuff happens it's a failure to translate coordinates from screen to widget or vice versa.

                                  My L-GPL'd C++ Logger github.com/ambershark-mike/sharklog

                                  1 Reply Last reply
                                  2
                                  • SGaistS Offline
                                    SGaistS Offline
                                    SGaist
                                    Lifetime Qt Champion
                                    wrote on last edited by
                                    #17

                                    Hi,

                                    IIRC, you receive the geometry of the cell you clicked so you are already painting on the right rectangle, no need to move anything around.

                                    Interested in AI ? www.idiap.ch
                                    Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

                                    1 Reply Last reply
                                    3
                                    • michalosM Offline
                                      michalosM Offline
                                      michalos
                                      wrote on last edited by
                                      #18

                                      Solved it by drawing the highlighting rectangle before the painter->translate.

                                      Thank You All for Your help.
                                      Now it seems logical, but I don't think I could figure out this by my self.

                                      1 Reply Last reply
                                      1

                                      • Login

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