In my project I have several QTreeView
widgets displaying data. The background color of the items in the QTreeView
changes depending on the data's type and association with other items.
Here is how those background colors are set:
QColor warning;
warning.setRgb(255, 86, 86);
model->itemFromIndex(index)->setData(warning, Qt::BackgroundRole);
This works, but I also want to have different background colors when an item is selected/hovered. I opted to use a stylesheet.
QTreeView::item:selected{background-color: #bedcf0;} //light blue
QTreeView::item:hover:selected{background-color: #94c8ea;} //darker blue
QTreeView::item:hover:!selected{background-color: #e6e6e6;} //gray
This provides the look I want, but only for items that have a white default background. If an item has a custom background color (set via Qt::BackgroundRole
) then these hover and selected colors completely override the current background color.
What I want to happen is have every item darken a set amount when hovered/selected, based on the current background color. This is tough because QStandardItem::setProperty()
doesn't exist.
Thanks for your time!
So I was able to solve this myself. (pointless bounty, idk why I handed over the 50 rep before checking if it worked.)
What I did was subclass
QStyledItemDelegate
and reimplement thepaint()
function..h
In this paint function I was able to check the index's UserRoles for a custom flag to decide the color I wanted. I can use
QStyle::State_Selected
andQStyle::State_MouseOver
to check if the index is selected or hovered.Using that information, I was able to write the logic to determine the colors I wanted. After that I had to draw in the background, icon, and text manually..cpp
Once that's done, I just apply the delegate to my
QTreeView
withmyTreeView->setItemDelegate(new MyStyledItemDelegate(myTreeView));
No stylesheets, background role changes, or eventFilters required. I've searched all over the internet for a solution and only found a lot of people with the same problem and no good answer. This is by far the simplest and most versatile way to achieve this I've come up with so I hope it helps anyone else who needs it :)
So I have an answer. Maybe you can tell me if it's ok for you and/or we can talk about it.
I created a custom
QTreeView
andQStandardItem
, overwritemouseMoveEvent(QMouseEvent *event)
and setsetMouseTracking(true);
of my tree.I got the item under the mouse with:
static_cast<QStandardItemModel*>(model())->itemFromIndex(indexAt(event->pos()))
With that I can get with item is hovered. Then in my custom item I have a function
hovered()
andnormal()
. When the item is hovered, the method hovered is called. When the mouse move, it put the item back to normal and rehovered it if it's still on it. The code:HoveredTreeView.cpp:
HoveredTreeView.h:
HoveredStandardItem.cpp:
HoveredStandardItem.h:
I tested it in a MainWindow. Here the constructor: