PDA

View Full Version : Get rid of the stupid frustrating focus rectangle in QTreeWidget



Carlsberg
16th June 2010, 14:28
Now what beautiful the life would have been if every widget had a function like this

void setFocusRectangleVisible(bool status)

But no, there is none. So after looking over the entire google, I found this example:

http://qt.nokia.com/developer/faqs/736

which works fine. I took that example and replaced some things in there to use it on my QTreeWidget.

Now I have this



void Style::drawControl(ControlElement element, const QStyleOption * option, QPainter * painter, const QWidget * widget ) const
{
if(element == CE_ItemViewItem)
{
const QStyleOptionViewItem *b = qstyleoption_cast<const QStyleOptionViewItem *>(option);
QStyleOptionViewItem *btn = (QStyleOptionViewItem *)b;

if (btn)
{
if (btn->state & State_HasFocus)
{
btn->state = btn->state ^ State_HasFocus;
}
}

QWindowsStyle::drawControl(element, btn, painter, widget);

}
else
{
QWindowsStyle::drawControl(element, option, painter, widget);
}
}


This is not working as expected because this test is NEVER true


if (btn->state & State_HasFocus)

Can someone please help me? What am I missing? Is the problem the fact that the focus is not on the item itself, but on the tree widget?

I'm using Qt 4.5

Lykurg
16th June 2010, 16:22
isn't it QStyle::State_Selected for items?

aamer4yu
17th June 2010, 06:10
What if you make a copy of the option ?
Not sure if const is causing some trouble, might be it is :rolleyes:

though I guess it is QStyle::State_hasFocus only, I had used it in delegate to get rid of that focus rect, and it worked for me in the delegate.

Carlsberg
17th June 2010, 09:11
I've tried wth Selected before posting here, it des not work...


What if you make a copy of the option ?
Not sure if const is causing some trouble, might be it is :rolleyes:

though I guess it is QStyle::State_hasFocus only, I had used it in delegate to get rid of that focus rect, and it worked for me in the delegate.

Ok, I've used an item delegate like this:


void MyStupidItemDelegate::paint(QPainter* painter, const QStyleOptionViewItem & option, const QModelIndex &index) const
{
QStyleOptionViewItem itemOption(option);

if (itemOption.state & QStyle::State_HasFocus)
{
itemOption.state ^= QStyle::State_HasFocus;
}

QStyledItemDelegate::paint(painter, itemOption, index);
}


Now the focus rectangle i gone, BUT the my style sheet is not applied anymore :D

Can you please advise how can I combine those to work together? Thank you :rolleyes:

wysota
17th June 2010, 09:28
Now what beautiful the life would have been if every widget had a function like this

void setFocusRectangleVisible(bool status)

But no, there is none.


treeWidget->setFocusPolicy(Qt::NoFocus);

... or reimplement the delegate (not the style) and ignore the focus flag from QStyleOptionViewItem in the painting routine.

aamer4yu
17th June 2010, 09:30
Are you also using the custom style ?

From the docs of Qt Style Sheets-

Warning: Qt style sheets are currently not supported for custom QStyle subclasses. We plan to address this in some future release.

Carlsberg
17th June 2010, 10:05
treeWidget->setFocusPolicy(Qt::NoFocus);

I now that, but that is not good. I want the focus, I just don't want the useless rectangle.



... or reimplement the delegate (not the style) and ignore the focus flag from QStyleOptionViewItem in the painting routine.

I don't understand this. I did this, which seems to be what you said, and the result is the same. The focus rectangle is not shown, but setStyleSheet has no effect anymnore, so the selection is some dark gray


class MyDelegate : public QItemDelegate
{
protected:
void paint(QPainter* painter, const QStyleOptionViewItem& option, const QModelIndex& index) const;
};

void MyDelegate::paint( QPainter * painter, const QStyleOptionViewItem & option, const QModelIndex & index ) const
{
QStyleOptionViewItem itemOption(option);

if (itemOption.state & QStyle::State_HasFocus)
{
qDebug("FOCUS");
itemOption.state ^= QStyle::State_HasFocus;
}

QItemDelegate::paint(painter, itemOption, index);
}

Carlsberg
17th June 2010, 10:06
Warning: Qt style sheets are currently not supported for custom QStyle subclasses. We plan to address this in some future release
Ah, ok, then it's normal behaviour. Now I guess I will have to try to paint everything in the paint() function

wysota
17th June 2010, 10:10
Subclass QStyledItemDelegate and not QItemDelegate. To be honest I'm not very fond of the idea of representing focus with selection. These are two different mechanisms. And as far as I remember you can define the focus rectangle using style sheets as well, you should dig deeper in the style sheet reference.

Carlsberg
17th June 2010, 10:29
Subclass QStyledItemDelegate and not QItemDelegate. To be honest I'm not very fond of the idea of representing focus with selection. These are two different mechanisms.
I have done both, as it can be seen above. The result is identical. Well, having an ugly rectangle over the nice selection is not only just ugly, but also extremely useless. Not to mention that nobody uses the tab key by going through many widgets. In 15 years I used the tab key only once, when the mouse died. And it was sick :cool:


And as far as I remember you can define the focus rectangle using style sheets as well, you should dig deeper in the style sheet reference.
I've done that, but found absolutely nothing :(

wysota
17th June 2010, 10:57
Try doing equivalents of these (I mean the selectors):
QListView::item:selected:!active {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #ABAFE5, stop: 1 #8588B2);
}

QListView::item:selected:active {
background: qlineargradient(x1: 0, y1: 0, x2: 0, y2: 1,
stop: 0 #6a6ea9, stop: 1 #888dd9);
}

Manipulating the "border" property might just work here.

Carlsberg
17th June 2010, 13:34
Ok, I've done it. The solution was to completely rewrite the delegate's paint() function for the following states:

QStyle::State_Selected && QStyle::State_Active
QStyle::State_Selected && !QStyle::State_Active
QStyle::State_MouseOver

and of course for the nothing state

For QStyle::State_MouseOver to be correctly set, you must set the viewport's attribute Qt::WA_Hover. That is a bug

http://bugreports.qt.nokia.com/browse/QTBUG-6063

I also made the background color to cover only the text part of the item. This is the final result, when active and selected plus a hovered item

4794

Thank you all for input

javimoya
4th November 2010, 23:11
Carlsberg, please... could you send me your solution??
I'm facing the same problem...
thank you very much

GUIDeveloper
24th August 2018, 15:29
Hey Carlsberg, please send me your solution.
I am fighting the same thing.

Thanks.

GD



Ok, I've done it. The solution was to completely rewrite the delegate's paint() function for the following states:

QStyle::State_Selected && QStyle::State_Active
QStyle::State_Selected && !QStyle::State_Active
QStyle::State_MouseOver

and of course for the nothing state

For QStyle::State_MouseOver to be correctly set, you must set the viewport's attribute Qt::WA_Hover. That is a bug

http://bugreports.qt.nokia.com/browse/QTBUG-6063

I also made the background color to cover only the text part of the item. This is the final result, when active and selected plus a hovered item

4794

Thank you all for input