首页 > 解决方案 > 如何禁用样式表中的焦点指示

问题描述

当我的 QDoubleSpinBox 聚焦时,它会得到一个蓝色轮廓(以“Fusion”风格):

在此处输入图像描述

我该如何关闭它?

标签: pythonpyqtpyqt5

解决方案


仅对样式表执行此操作是可行的,但有一个重要缺点:像 QSpinBox 这样的复杂小部件的样式需要正确设置所有子控件属性。

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

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

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

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

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

spinbox 与样式表的区别

不幸的是,几乎没有直接的方法可以恢复箭头的默认绘制,因为使用样式表可以防止这种情况发生。因此,唯一的解决方案是提供控件的属性,如有关自定义 QSpinBox 的示例中所述。

不过,还有另一种选择,使用QProxyStyle。诀窍是在调用默认实现之前拦截drawComplexControl()实现中的控件并删除State_HasFocus选项的标志。
在下面的示例中,我还在移除标志之前检查了焦点,以便提供足够的视觉反馈,并且我还移除了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()or值lighter()以提供更好的差异化。


推荐阅读