【问题标题】:Style QtComboBox, QListViewItem - Set text paddingStyle QtComboBox, QListViewItem - 设置文本填充
【发布时间】:2016-01-29 16:14:35
【问题描述】:

信息:Qt 4.8,Qt 设计器

我正在努力在组合框下拉菜单上设置文本项的填充。我的理解是整个是 QComboBox 小部件,而下拉部分是一个 QListView。但我无法确定使用什么 css 选择器来更改下拉列表中文本项的样式。

我希望悬停项目的背景颜色一直向左延伸,而不是留下 5 像素的边距。文字本身排列得很好,只是左边的白色空白让我很烦。

如果我可以删除突出显示项目周围的虚线边框,我会很棒。

我想我只是没有使用正确的项目选择器。我试过 QListView::item 和 QListViewItem。这是我应用于组合框的 CSS。

QComboBox{
border:                 none;
background-color:   rgb(87, 96, 134);
color:                      rgb(255, 255, 255);
font-weight:            bold;
padding:                    5px 

}

QComboBox::drop-down{
    border:                 none;
    background-color:   rgb(87, 96, 134);
    color:                      rgb(255, 255, 255);
    font-weight:            bold;
    padding:                    0px;
}

QComboBox::down-arrow{
    image:                      url(:/icons/combobox_down_arrow.png);
    padding-right:          5px;
}

QListView{
    border:                 none;
    color:                      rgb(87, 96, 134);
    background-color:   rgb(255, 255, 255);
    font-weight:            bold;
    selection-background-color: rgb(47, 175, 178);
    show-decoration-selected: 1;
    margin-left:                -10px;
    padding-left    :           15px;
}

QListView::item:hover{

    background-color:   rgb(47, 175, 178);
    border:                 none;
}

想法?

【问题讨论】:

  • 请提供jsfiddle。
  • @alirezasafian jsfiddle 可以与 Qt 一起使用吗?
  • 我认为没有。
  • fiddle/sn-p 肯定能帮到你。
  • 这是在 QtDesigner 中。您弹出一个 QComboBox 并应用上面包含的样式表代码。除此之外,我无法做任何 sn-p 或小提琴。

标签: css qt


【解决方案1】:

可以通过设置 undocumented property outline 仅使用 CSS 来移除圆点边框:

QComboBox QAbstractItemView {
    outline: none;
}

QListView 也可以在这个选择器中使用。在这个例子中使用了QAbstractItemView,因为它是QListView 的一个基类。请注意,此属性不是针对每个项目设置的,而是针对项目的外部容器设置的。

还有其他方法可以使用编码去除虚线边框,例如QT - CSS: decoration on focus


看起来需要更改代码以获得更好的填充灵活性。 QComboBox 基于 QItemDelegate 使用自己的 QAbstractItemDelegate 私有实现。但是,其他控件使用QStyledItemDelegate (QStyledItemDelegate vs. QItemDelegate)。这就是为什么项目的 CSS 选择器 (QListView::item) 对 QComboBox 项目没有影响。

源码中有如下注释和解释:

请注意,此类故意不使用QStyledItemDelegate
Vista 不使用组合框的新主题,可能有 使用新类的其他副作用

如果上面的注释没有问题,可以将QStyledItemDelegate设置为QComboBox对象:

QComboBox *combobox = new QComboBox;
combobox->setItemDelegate(new QStyledItemDelegate(combobox));

现在,不再需要 selection-background-color 属性。可以自定义::item

QComboBox QAbstractItemView::item {
    border: none;
    padding-left: 5px;
}

QComboBox QAbstractItemView::item:selected {
    background: rgb(47, 175, 178);
    padding-left: 5px;
}

请注意,要设置内边距,还需要至少提供边框或背景属性以及内边距。否则不考虑 padding 属性。

使用选择器::item:selected 代替:hover,因为项目也可以通过键盘选择。


虽然有文件证明可以为QComboBox 设置自定义view,但它并不是那么简单。 QComboBox 也可以有分隔项。如果QComboBox 中没有分隔项,则上述解决方案可以正常工作。要处理分隔符,项目委托也应该知道它们。

可以继承QStyledItemDelegate 并从QComboBoxDelegate 的Qt 私有实现中复制所需的函数。该解决方案不是很好。它可能在新 Qt 版本中不可移植。 Qt5中QComboBoxDelegate的实现与Qt4不兼容。但是,Qt5 可以与 Qt4 实现一起使用,所以这个类可以取自 Qt4。 QItemDelegate 基类被 QStyledItemDelegate 替换:

class ComboBoxDelegateStyled : public QStyledItemDelegate
{ 
    Q_OBJECT
public:
    ComboBoxDelegateStyled(QObject *parent, QComboBox *cmb) :
        QStyledItemDelegate(parent), mCombo(cmb) {}

    static bool isSeparator(const QModelIndex &index) {
        return index.data(Qt::AccessibleDescriptionRole).toString() == QLatin1String("separator");
    }

protected:
    void paint(QPainter *painter,
               const QStyleOptionViewItem &option,
               const QModelIndex &index) const {
        if (isSeparator(index)) {
            QRect rect = option.rect;
            if (const QStyleOptionViewItemV3 *v3 = qstyleoption_cast<const QStyleOptionViewItemV3*>(&option))
                if (const QAbstractItemView *view = qobject_cast<const QAbstractItemView*>(v3->widget))
                    rect.setWidth(view->viewport()->width());
            QStyleOption opt;
            opt.rect = rect;
            mCombo->style()->drawPrimitive(QStyle::PE_IndicatorToolBarSeparator, &opt, painter, mCombo);
        } else {
            QStyledItemDelegate::paint(painter, option, index);
        }
    }

    QSize sizeHint(const QStyleOptionViewItem &option,
                   const QModelIndex &index) const {
        if (isSeparator(index)) {
            int pm = mCombo->style()->pixelMetric(QStyle::PM_DefaultFrameWidth, 0, mCombo);
            return QSize(pm, pm);
        }
        return QStyledItemDelegate::sizeHint(option, index);
    }
private:
    QComboBox *mCombo;
};

继承QComboBox 以使用ComboBoxDelegateStyled 是有意义的:

class ComboBoxStyled : public QComboBox
{
public:
    explicit ComboBoxStyled(QWidget *parent = 0) : QComboBox(parent) {
        setItemDelegate(new ComboBoxDelegateStyled(this, this));
    }
};

现在可以使用类 ComboBoxStyled 代替 QComboBox。它支持组合框分隔符绘制,还支持::item的CSS。

自定义QComboBox分隔符的类似解决方案:how to add stylesheet for separator in QCombobox


PyQt

上述行为对 PyQt 有效。可以使用outline 删除虚线边框,并设置样式项目委托以自定义 CSS ::item

styledComboBox = QtGui.QComboBox()
delegate = QtGui.QStyledItemDelegate()
styledComboBox.setItemDelegate(delegate)

在这种情况下,组合框分隔符显示为没有文本的常规项目。 也可以创建自定义委托来处理分隔符。

【讨论】:

  • 我的话。我宁愿希望“不傻,改用这个 css 位”。明天早上我会试一试,看看我能做些什么。我正在使用 PyQt,所以我不确定我可以重新编码多少东西。我明天再看一遍。不过,感谢您提供如此明智和详细的答复。
  • @Oliver 对于 PyQt,一切都是一样的。我更新了答案。看起来,对于自定义分隔符,仍然需要编写自定义委托。我讨厌项目中的这种调整,但这是解决方案。如果您不关心组合框分隔符,设置QStyledItemDelegate 就足够了(使用QComboBox 的自定义子类来创建许多这样的组合框是有意义的)。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-07-12
  • 2015-09-02
  • 1970-01-01
  • 2018-10-28
  • 1970-01-01
相关资源
最近更新 更多