QComboBox的文字居中,下拉选项实现起来非常简单,但是本身的控件文本框默认是靠左的,想让他居中非常费劲,网上找到的一些方法都特别复杂,最后实现出来或多或少都有问题,没能完全满足我的需求。但最后终于找到一篇可以实现的了,虽然代码我也没太理解,但是效果不错。这里先感谢一下这篇文章:QComboBox文字居中的一种解决办法
实现方式
然后呢,他主要的实现方式是QComboBox控件重载paintevent,光是这一步就可以实现功能了。逻辑大概是重新绘制吧。
void CenterComboBox::paintEvent(QPaintEvent *ev)
{
// 该代码是Qt默认实现,直接拷贝一份
QStylePainter painter(this);
painter.setPen(palette().color(QPalette::Text));
// draw the combobox frame, focusrect and selected etc.
QStyleOptionComboBox opt;
initStyleOption(&opt);
painter.drawComplexControl(QStyle::CC_ComboBox, opt);
if (currentIndex() < 0)
opt.palette.setBrush(QPalette::ButtonText, opt.palette.brush(QPalette::ButtonText).color().lighter());
// draw the icon and text
//painter.drawControl(QStyle::CE_ComboBoxLabel, opt); //不需要再绘制文本内容
// 以上代码是Qt默认实现
painter.end();
// 在文本区域绘制按钮文本
QPainter painter2(this);
QStyleOptionButton buttonOpt;
buttonOpt.initFrom(this); // 主要是一些窗口状态,hover、enable等
QRect editRect = this->style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this);
buttonOpt.rect = editRect; // 设置按钮区域为QComboBox的文本区域
buttonOpt.text = opt.currentText; // 设置文本
// 绘制QStyle::CE_PushButtonLabel
this->style()->drawControl(QStyle::CE_PushButtonLabel, &buttonOpt, &painter2, this);
}
放到我本身的代码当中,外部对该对象进行样式表设置setStyleSheet,也是可以成功应用的,虽然和列表选项没有完全对准,但是是正常的啦。
甚至可以靠右,主要取决于样式表怎么写的(text-align:right;),可以参考一下我这段:
QString cb_setss = QString("QComboBox {\
border: 2px solid #f3f3f3;\
color: rgb(80, 80, 80);\
background-color: rgb(255, 255, 255);\
border-radius: %0px;/*圆角*/\
padding: 1px 2px 1px 2px; /*针对于组合框中的文本内容*/\
/*min-width: 0px; # 组合框的最小宽度*/\
/*text-align:right;*/\
/*min-height: 5em;*/\
}\
QComboBox::hover {\
color:rgba(0, 185, 179, 1);\
border-color:rgba(0, 185, 179, 1);\
background: rgba(239, 250, 250, 1);\
}\
QComboBox::drop-down {\
subcontrol-origin: padding;\
subcontrol-position: top right;\
width: %1px;\
border-top-right-radius: 3px;\
border-bottom-right-radius: 3px;\
/*padding-right: 50px;*/\
}\
QComboBox::down-arrow {\
border-image: url(:/sdzblgxx/setup/btn_down.png);\
width: %2px;\
height: %3px;\
}\
QComboBox QAbstractItemView {\
border: 2px solid #f3f3f3;\
background-color: rgb(255, 255, 255);\
border-radius: 10px;\
padding: 1px 2px 1px 2px;\
}\
QComboBox QAbstractItemView::item {\
height: %4px;\
color: rgb(80, 80, 80);\
}\
QComboBox QAbstractItemView::item:hover {\
color: #FFFFFF;\
background-color: rgba(0, 185, 179, 1);\
}\
QComboBox QAbstractItemView::item:selected {\
color: #FFFFFF;\
background-color: rgba(0, 185, 179, 1);\
}").arg(5*scale).arg(25*scale).arg(20*scale).arg(20*scale).arg(combobox_item_height*scale);
ui->cb_screenShareType->setStyleSheet(cb_setss);
针对分辨率的适配,我增加了一些scale缩放比相关的参数,读者可以借鉴使用。
一些弯路
稍微了解一下QCombobox的构成,会发现里面集成了一个QLineEdit。当QCombobox打开了编辑使能后,会江QLineEdit显示出来,此时样式和字体都要单独对QLineEdit设置才能保证样式统一。
有意思的地方来了,如果对QLineEdit设置了以下代码,setAlignment让字体居中,设置只读,关闭使能,再将他设置成透明。结果观感上使能满足我们要求的
//测试
combobox->setEditable(true);
combobox->lineEdit()->setAlignment(Qt::AlignCenter);
combobox->lineEdit()->setReadOnly(true);
combobox->lineEdit()->setEnabled(false);
// combobox->lineEdit()->hide();
combobox->lineEdit()->setMouseTracking(true);
combobox->lineEdit()->setStyleSheet("background:transparent;border-width:0;border-style:outset");
combobox->lineEdit()->setAttribute(Qt::WA_TransparentForMouseEvents);
但是他有一个问题,点击非最右侧下拉按钮的区域,即QLineEdit的区域时,无法让QCombobox展开下拉框。这个问题即便重载了focusInEvent和mouseReleaseEvent也没能成功实现,逻辑相对太过复杂了。所以这个方法被我废弃掉了,但在一些情况下可以尝试这样去做,效果也不错的。