Why is QTreeView highlighting wrong row (different than selection)
-
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 64bitAny idea where I should look for bugs?
Below are two examples of my widget
mouse was howering over the row where the two buttons (rectangles) are
-
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?
-
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); }
-
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 ?
-
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?
-
@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. -
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?
-
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 }
-
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 ?
-
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(" "); textCursor.movePosition(QTextCursor::EndOfLine, QTextCursor::MoveAnchor); textCursor.insertImage(stanPoint); textCursor.movePosition(QTextCursor::End, QTextCursor::MoveAnchor); textCursor.insertHtml(" "); } 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
-
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
-
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);
-
@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.
-
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.