It is possible to remove the dotter border using only CSS by setting undocumented property outline
:
QComboBox QAbstractItemView {
outline: none;
}
QListView
also can be used in this selector. QAbstractItemView
is used in this example, since it is a base class of QListView
. Note that this property is set not per item but for the external container of items.
There are other ways to remove the dotted border using coding, for example QT - CSS: decoration on focus
It looks that it is needed to change the code to have better flexibility with padding. QComboBox
uses its own private implementation of QAbstractItemDelegate
based on QItemDelegate
. However, other controls use QStyledItemDelegate
(QStyledItemDelegate
vs. QItemDelegate
). That is why CSS selectors for items (QListView::item
) does not have an effect on QComboBox
items.
There is the following comment with explanation in the source code:
Note that this class is intentionally not using QStyledItemDelegate
Vista does not use the new theme for combo boxes and there might be
other side effects from using the new class
If the above comment is not a problem, it is possible to set QStyledItemDelegate
to QComboBox
objects:
QComboBox *combobox = new QComboBox;
combobox->setItemDelegate(new QStyledItemDelegate(combobox));
Now, the property selection-background-color
is not needed anymore. It is possible to customize ::item
:
QComboBox QAbstractItemView::item {
border: none;
padding-left: 5px;
}
QComboBox QAbstractItemView::item:selected {
background: rgb(47, 175, 178);
padding-left: 5px;
}
Note that to set padding it is also needed to provide, for example, at least border or background property together with padding. Otherwise the padding property is not taken into account.
The selector ::item:selected
is used instead of :hover
, since items can be also selected by keyboard.
Although it is documented that it is possible to set custom view for QComboBox
it is not so simple. QComboBox
can also have separator items. The above solution works fine if there are no separator items in QComboBox
. To handle separators the item delegate should also know about them.
It is possible to subclass QStyledItemDelegate
and copy required functions from Qt private implementation of QComboBoxDelegate
. That solution is not very nice. It may be non-portable with new Qt versions. The implementation of QComboBoxDelegate
in Qt5 is not compatible with Qt4. However, Qt5 can work with Qt4 implementation, so this class can be taken from Qt4. The QItemDelegate
base class is replaced by 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;
};
It makes sense to subclass QComboBox
to use ComboBoxDelegateStyled
:
class ComboBoxStyled : public QComboBox
{
public:
explicit ComboBoxStyled(QWidget *parent = 0) : QComboBox(parent) {
setItemDelegate(new ComboBoxDelegateStyled(this, this));
}
};
Now the class ComboBoxStyled
can be used instead of QComboBox
. It supports combo box separator drawing and also it supports CSS for ::item
.
Similar solution for customizing QComboBox
separator: how to add stylesheet for separator in QCombobox
PyQt
The above behavior is valid for PyQt. It is possible to remove dotted border using outline
and to set styled item delegate to customize CSS ::item
:
styledComboBox = QtGui.QComboBox()
delegate = QtGui.QStyledItemDelegate()
styledComboBox.setItemDelegate(delegate)
In such case the combo box separator is displayed as a regular item without text.
It is also possible to create custom delegate to handle separators.