使用 QSS 设置 QAbstractSpinBox 样式时从 QColorDialog 中的 QSpinBoxes 中排除样式

Excluding style from QSpinBoxes in QColorDialog when using QSS to style QAbstractSpinBox

我一直在使用 Jorgen-VikingGod 的优秀 Qt-Frameless-Window-DarkStyle 作为基准,使用 QSS 设计 Qt 桌面应用程序的样式。不幸的是,我们还必须在现场支持相当过时的平板设备(运行 Windows),这意味着我们的一些客户实际上无法使用微小的旋转框按钮。

建议的解决方案是创建大的 +/- 按钮并将它们放在旋转框的相对两侧:

但是,这会导致某些 Qt 便利控件出现不良行为,例如 QColorDialog:

我的QSS码如下:

QAbstractSpinBox {
  height: 18px;
  border-radius: 2px;
  border: 1px solid rgba(38,38,38,255);
}
QAbstractSpinBox:focus {
  border-color: palette(highlight);
}
QAbstractSpinBox::up-button {
  subcontrol-origin: border;
  subcontrol-position: center right;
  width: 18px;
  height: 18px;
  border-image: url(:/darkstyle/icon_spin_box_button.png);
  margin-left: 1px;
}
QAbstractSpinBox::down-button {
  subcontrol-origin: border;
  subcontrol-position: center left;
  width: 18px;
  height: 18px;
  border-image: url(:/darkstyle/icon_spin_box_button.png);
  margin-right: 1px;
}
QAbstractSpinBox::up-button:pressed {
  border-image: url(:/darkstyle/icon_spin_box_button_pressed.png);
}
QAbstractSpinBox::down-button:pressed {
  border-image: url(:/darkstyle/icon_spin_box_button_pressed.png);
}
QAbstractSpinBox::up-arrow {
  image: url(:/darkstyle/icon_spin_box_plus_sign.png);
  width: 14px;
  height: 14px;
}
QAbstractSpinBox::down-arrow {
  image: url(:/darkstyle/icon_spin_box_minus_sign.png);
  width: 14px;
  height: 14px;
}
QAbstractSpinBox::up-arrow:disabled,
QAbstractSpinBox::up-arrow:off {
  image: url(:/darkstyle/icon_spin_box_plus_sign_disabled.png);
  width: 14px;
  height: 14px;
}
QAbstractSpinBox::down-arrow:disabled,
QAbstractSpinBox::down-arrow:off {
  image: url(:/darkstyle/icon_spin_box_minus_sign_disabled.png);
  width: 14px;
  height: 14px;
}

到目前为止,我已经尝试用 .QSpinBox, .QDoubleSpinBox 替换 QAbstractSpinBox 选择器,但这产生了一个看起来像默认样式混合的混乱(up/down 箭头堆叠在对)符合我的风格(深色边框、凸起外观等)。

QSS 似乎不支持 CSS3 风格的 :not 选择器,也没有提供我可以使用的等效选择器。

综上所述,除了 QColorDialog 中的旋转框外,我是否可以通过任何方式将此样式应用到我的应用程序中的每个旋转框?或者任何不涉及我在我的应用程序中的每个旋转框实例上通过 ID/objectName 设置此样式的替代方法?查看源代码,似乎 QColorDialog 使用 QSpinBox 派生的 class 命名为 QColSpinBox,所以如果我可以排除特定的子 class,那也可以了

您可以使用 CSS/QSS 设置 QColorDialog 的某些组件的样式。

所以你可以添加这样的东西:

QColorDialog QSpinBox {
    min-width: 3.5em;
    text-align: center;
}

为旋转框添加一些额外的空间。我还添加 min-widthmin-heightQColorDialog QColorPicker 像这样:

QColorDialog QColorPicker {
    min-width: 20em;
    min-height: 20em;
    border: solid 1px gray;
}

谢谢你的起点!!!在与 Qt 5.9.2 进行了长时间的斗争之后,我发现了如何将按钮恢复到默认/本机状态:

QColorDialog QPushButton {background-color:native; color:native; border: native; border-radius:-1px; padding: native;}

这里没有 auto 也没有 default 值。

native 是关键,但是对于边框和背景你必须取消任何 border-radius 因为下面的代码:

void QStyleSheetStyle::drawComplexControl(ComplexControl cc, const QStyleOptionComplex *opt, QPainter *p,
                                          const QWidget *w) const
{
    RECURSION_GUARD(baseStyle()->drawComplexControl(cc, opt, p, w); return)

    QRenderRule rule = renderRule(w, opt);

    switch (cc) {
    case CC_ComboBox:
        if (const QStyleOptionComboBox *cmb = qstyleoption_cast<const QStyleOptionComboBox *>(opt)) {
            QStyleOptionComboBox cmbOpt(*cmb);
            cmbOpt.rect = rule.borderRect(opt->rect);
            if (rule.hasNativeBorder()) {
                rule.drawBackgroundImage(p, cmbOpt.rect);
                rule.configurePalette(&cmbOpt.palette, 
            ...
            ...
            ...

... ... ...
bool hasNativeBorder() const {
    return bd == 0
           || (!bd->hasBorderImage() && bd->styles[0] == BorderStyle_Native);
}
... ... ... 
void QRenderRule::fixupBorder(int nativeWidth)
{
if (bd == 0)
    return;

if (!bd->hasBorderImage() || bd->bi->pixmap.isNull()) {
    bd->bi = 0;
    // ignore the color, border of edges that have none border-style
    QBrush color = pal ? pal->foreground : QBrush();
    const bool hasRadius = bd->radii[0].isValid() || bd->radii[1].isValid()
                           || bd->radii[2].isValid() || bd->radii[3].isValid();
    for (int i = 0; i < 4; i++) {
        if ((bd->styles[i] == BorderStyle_Native) && hasRadius)
            bd->styles[i] = BorderStyle_None;

即使您告诉将边框设置为 native 如果您之前设置了边界半径... 您必须为半径提供无效值。半径存储在 QSize 中,对于 -1、-1、-1、-1 无效。

none 将使 hasNativeBorder 失败导致根本没有边框/背景...

为什么不使用简单的 qt-all-native: true 或类似的 QSS 扩展...