QPushButton 不遵守 QIcon 模式更改

QPushButton not respecting QIcon mode changes

当应用 QIconQPushButton::setIcon() 时,模式更改似乎不遵循为 QIcon

设置的模式更改
QIcon helpIcon;
helpIcon.addPixmap(QPixmap(":/icons/style/help.png"), QIcon::Normal);
helpIcon.addPixmap(QPixmap(":/icons/style/help_hover.png"), QIcon::Active); //ignored?

QPushButton *myButton = new QPushButton(this);
myButton->setIcon(helpIcon);

我希望发生的情况是,当按钮悬停时,图标应该从一个像素图变为另一个像素图。相反,图标保持不变。它仅在按下按钮时发生变化。我已经尝试了 QIcon::StateQIcon::Mode 的所有组合,没有任何变化。

运行 Qt 5.12.1

这就是 QPushButton 处理状态(因此图标 mode/state)的方式,这与 QToolButton 不同。更具体地说,它是当前 QStyle 子类如何使用按钮状态信息来绘制图标。例如,这里是 QCommonStyle 中的 QPushButton::paintEvent() code (follow that to see initStyleOption() call where state data is initialized), then the style options are handed off to the currently active QStyle (which could be eg. WindowsVista/Macintosh/Fusion/StyleSheets depending on OS or settings). Then if we look at, for example, the relevant QFusionStyle code we can see that the icon Active mode is only used when the button has focus. Or same(Windows/WindowsVista/Macintosh 样式全部回落)。

要解决此问题,您可以使用 CSS 并为 QPushButton:hover 状态设置 image 属性,或者实现您自己的 QProxyStyle::drawControl() 方法CE_PushButtonLabel 控制元素。

CSS: QPushButton:hover { image: url(/path/to/icon.png); }

我通过 subclassing QPushButton 并监听进入和离开事件解决了这个问题。 class 在基本图标和悬停图标之间切换。这对我来说比样式表更有用,因为我根据用户的 DPI 调整图标大小。

class CustomButton : public QPushButton
{
    Q_OBJECT
public:
    CustomButton(QWidget *parent = nullptr);

    void setBaseIcon(QIcon icon){
        baseIcon = icon;
        setIcon(baseIcon);
    }

    void setHoverIcon(QIcon icon){hoverIcon = icon;}

private:
    QIcon baseIcon;
    QIcon hoverIcon;

protected:
    virtual void enterEvent(QEvent *){
        setIcon(hoverIcon);
        update();
    }

    virtual void leaveEvent(QEvent *){
        setIcon(baseIcon);
        update();
    }
};