Solved Need help with QStyle states of QToolButton when disabling the "State_Sunken"-flag
-
I have a QToolBar that only shows icons instead of whole buttons. In order to complete the look, I tried to disable the "sunken" look of a QToolButton when in its "checked"-state.
I removed State_Sunken from the QStyle-flags when the QToolButton is in its On-state, which works correctly and the button did not appear "sunken" anymore:void MyToolButton::paintEvent(QPaintEvent* /*in_p_event*/) { QStylePainter painter(this); QStyleOptionToolButton opt; initStyleOption(&opt); if (opt.state.testFlag(QStyle::State_On)) { opt.state = opt.state & QStyle::State_Sunken; } painter.drawComplexControl(QStyle::CC_ToolButton, opt); }
But then it also appeared deactivated (greyed out) in its On-state. So I added the State_Enabled-flag:
... opt.state = opt.state & QStyle::State_Sunken | QStyle::State_Enabled; ...
After this, the icon didn't appear deactivated anymore. But it still didn't show the icon variation I set for "On" (checked). I tried also setting the State_On-flag, but that brought the old behavior back, including the "sunken" look.
I guess my question now is: Which QStyle-flag only sets the "On"-icon of the QToolButton? -
See the code in qcommonstyle.cpp:1702 ff:
... QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; QIcon::Mode mode; if (!(toolbutton->state & State_Enabled)) mode = QIcon::Disabled; ... pm = toolbutton->icon.pixmap(qt_getWindow(widget), toolbutton->rect.size().boundedTo(toolbutton->iconSize), mode, state);
-
See the code in qcommonstyle.cpp:1702 ff:
... QIcon::State state = toolbutton->state & State_On ? QIcon::On : QIcon::Off; QIcon::Mode mode; if (!(toolbutton->state & State_Enabled)) mode = QIcon::Disabled; ... pm = toolbutton->icon.pixmap(qt_getWindow(widget), toolbutton->rect.size().boundedTo(toolbutton->iconSize), mode, state);
-
@Christian-Ehrlicher Thank you so much, that did the trick!
Here's my code now:
void MyToolButton::paintEvent(QPaintEvent* /*in_p_event*/) { QStylePainter painter(this); QStyleOptionToolButton opt; initStyleOption(&opt); if (opt.state.testFlag(QStyle::State_On)) { opt.state = opt.state & QStyle::State_Sunken | QStyle::State_Enabled; QIcon::Mode icon_mode = QIcon::Normal; if (opt.state.testFlag(QStyle::State_Active)) icon_mode = QIcon::Active; else if (opt.state.testFlag(QStyle::State_Selected)) icon_mode = QIcon::Selected; else if (false == opt.state.testFlag(QStyle::State_Enabled)) icon_mode = QIcon::Disabled; opt.icon = QIcon(this->icon().pixmap(rect().size(), icon_mode, QIcon::On)); } painter.drawComplexControl(QStyle::CC_ToolButton, opt); }
-
Wouldn't it be better to set the correct icons for the different states than re-setting the icon every time?
-
@Christian-Ehrlicher They are set, but the whole thing ceases to work when I unset the QStyle::State_Sunken-flag.
-
Since the code I posted above doesn't touch Sunken at all I wonder why it should not work
-
@qwasder85
I'm not sure how to archive what you want, but you are wrong at the very beginning.opt.state = opt.state & QStyle::State_Sunken;
This means : clear all the other states, only leave
State_Sunken
as it was... -
@Bonnie How would I unset just this one flag and not change anything else (bitwise operations and me do not see eye to eye)?
-
Since it's an enum encapsulated in a QFlag you don't have to worry about bit-setting: https://doc.qt.io/qt-5/qflags.html#setFlag -
@qwasder85
From qtoolbutton.cpp:if (d->down) option->state |= QStyle::State_Sunken;
And from the QAbstractButton doc:
down : bool
This property holds whether the button is pressed downSo I don't think this state is what you want...
-
@Christian-Ehrlicher Using just opt.state.setFlag(QStyle::State_Sunken, false) does not work. The button remains sunken when checked.
@Bonnie It has to be. I tried pretty much every other flag that sounded appropriate.
-
@qwasder85 I don't see a reason why this should be the case. Please provide a minimal, reproducible example.
-
@qwasder85
I tried to print the state when a toolbutton is checkedif (opt.state.testFlag(QStyle::State_On)) { qDebug() << opt.state.testFlag(QStyle::State_Sunken); qDebug() << QString("0x%1").arg(opt.state, 8, 16, QChar('0')); }
The result is:
false "0x00011021"
Apparently
State_Sunken
(0x00000004) is not set by default unless it is being pressed down. -
Which bits are set when can also be seen in the code: https://code.woboq.org/qt5/qtbase/src/widgets/widgets/qtoolbutton.cpp.html#261
-
@Christian-Ehrlicher I'm creating a small example right now.