如何禁用样式表中的焦点指示器

How to dissable the focus indication in stylesheet

当我的 QDoubleSpinBox 获得焦点时,它会得到一个蓝色轮廓(以“Fusion”样式):

如何关闭此功能?

仅使用样式表来做到这一点 可行,但有一个重要的缺点:为 QSpinBox 等复杂小部件设置样式 需要 才能正确设置 所有子控件属性。

基本解决方案是为小部件设置边框:

QSpinBox {
    border: 1px inset palette(mid);
    border-radius: 2px;
}

请记住,提供适当的焦点可见响应确实重要;您可能不喜欢 Fusion 样式提供的“发光”(和颜色),但是无论小部件是否具有焦点,它都应该始终可见,即使它具有闪烁的文本光标。您可以通过使用 :focus 选择器指定稍微不同的颜色来做到这一点:

QSpinBox:focus {
    border: 1px inset palette(dark);
}

不幸的是,正如开头所解释的,这有一个重要的缺点:一旦应用了样式表,小部件绘制就会回到基本的原始方法(右边的旋转框使用上面的样式表):

不幸的是,几乎没有直接的方法来恢复箭头的默认绘制,因为使用样式表会阻止这种情况。因此,唯一的解决方案是提供控件的属性,如 examples about customizing QSpinBox.

中所述

不过,还有一个替代方案,即使用 QProxyStyle. The trick is to intercept the control in the drawComplexControl() 实现并在调用默认实现之前删除该选项的 State_HasFocus 标志。
在下面的示例中,我还检查了焦点 before 移除标志以提供足够的视觉反馈,并且我还移除了悬停时显示发光效果的 State_MouseOver 标志.

class Proxy(QtWidgets.QProxyStyle):
    def drawComplexControl(self, cc, opt, qp, widget=None):
        if cc == self.CC_SpinBox:
            opt = QtWidgets.QStyleOptionSpinBox(opt)
            if opt.state & self.State_HasFocus:
                opt.palette.setColor(QtGui.QPalette.Window, 
                    opt.palette.color(QtGui.QPalette.Window).darker(100))
            else:
                opt.palette.setColor(QtGui.QPalette.Window, 
                    opt.palette.color(QtGui.QPalette.Window).lighter(125))
            opt.state &= ~(self.State_HasFocus | self.State_MouseOver)
        super().drawComplexControl(cc, opt, qp, widget)

# ...
app = QtWidgets.QApplication(sys.argv)
app.setStyle(Proxy())
# ...

请注意,上述“颜色校正”仅适用于 Fusion 样式和其他使用 Window 调色板角色绘制边框的样式。例如,Windows 样式根本不考虑它,或者您可能希望使用更高的 darker()lighter() 值以提供更好的区分。