本文会尽可能解释一些内容,所以会显得有点长。

关于QComboBox文字的居中,网上提供的主流方案是,通过 QComboBox::setEditable 设置为可编辑状态,再获取 QComboBox::lineEdit 设置为只读并居中文字。

该方案的缺点在于改变了不可编辑状态下QComboBox的交互行为,例如,点击文本区域不会弹出列表,原因是QComboBox的一些交互行为依赖于 editable 属性,虽然可以通过自定义鼠标事件等方式完善,但不同平台上的交互又有细微的区别。

对此,这里提出另一种解决方案,尽可能避免影响QComboBox原生的交互,有点复杂,从思路上,也许能解决更多的类似问题。

一些基本原理

Qt虽然提供了 style sheet 方式设置控件样式,但Qt并没有将对应的QStyleSheetStyle公开。Qt的基础控件都是使用了QStyle接口绘制的,在使用 style sheet 时,大部分样式,如颜色、字体、边框等,在绘制时会从样式表中读取并覆盖QStyleOption,用户代码无法感知到该过程,特别是当设置了 hover、pressed 动作下的样式时。所以绘制的过程只能交给QStyle去绘制控件。

不过,QStyle接口并不关心QPainter参数的绘制目标,例如可以通过 QWidget::render 来截取控件内容。Qt也没有限制在A控件上绘制B控件。

另外,尽管Qt文档里说明了不同控件的style sheet应用范围,但实际样式定义了就会存在,即使样式对某些控件本身无效。

所幸,QComboBox和QPushButton的绘制事件比较简单,不涉及私有接口,可以借用一些源码里的绘制逻辑,所以重写 QComboBox::paintEvent

	// 该代码是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);	

需要注意的是:

  • 最后通过 QStyle::drawControl 仅绘制 QStyle::CE_PushButtonLabel ,是由于 QStyle::CE_PushButton 会绘制边框等样式,如果QComboBox设置了边框,会重复画一遍。
  • QStyle::drawControl 最后一个参数必须传QComboBox对象,样式需要通过窗口来获取。
  • 可以在QComboBox的样式中设置 text-align 来控制文本的对齐,虽然对QComboBox本身无效,但对QPushButton有效
  • 通过设置按钮文本绘制区域来控制位置,但可能会存在某些特殊的样式没有计算在内。

hover状态下的样式同样能够保留,由于未增加其他子控件,交互逻辑也没有变化。

一开始考虑使用组合的方式,在QComboBox上覆盖QLabel来实现居中,但QStyle在应用的过程中,针对QComboBox子控件的样式做了过滤,样式并不会生效。Qt有个私有的属性 Qt::WA_StyleSheet 可以跳过过滤,但在重设 style sheet 时可能引起异常。

还有一种比较麻烦的方案是,默认实现里,painter.drawControl(QStyle::CE_ComboBoxLabel, opt) 这段执行前,通过字体信息计算当前文本宽度,修改opt的rect属性,使默认的文本绘制刚好显示在中间。

QComboBox *combox = new QComboBox;static_cast&lt;QStandardItemModel*&gt;(combox-&gt;view()-&gt;model())-&gt;item(positon)-&gt;setTextAlignment(Qt::AlignCenter);每次只能修改一个item的文字位置... 一. 设置背景颜色+取消边框+取消容器内距离 setStyleSheet("background-color:rgb(63,63,63);padding:0px;border:0px"); setStyleSheet("gridline-color: rgb(255, 0, 0);\nbackgroun... 不知道你有没有遇到过这样的需求,将一个QComboBox文字居中显示。我最近遇到了这样的需要,主要是要和其他的控件显示进行匹配,这也就要求我们必须将下拉列表的文字居中显示。这种需求可能实现的方式会有好多种,但我一直坚信,能用原生的就用原生的,或者在原生的控件之上进行一些特例化的改动,让其满足我们的需求是最简单的方式,并且不会过多的影响样式表设置。所以这儿我还是选择了QComboBox,而我们要做的事情就是怎样将他的文字居中显示。... Qt QComboBox内容居中Qt-QComboBox内容居中设置1. 显示内容居中2 .下拉菜单内容居中 Qt-QComboBox内容居中设置 1. 显示内容居中 QComboBox *comboBox = new QComboBox; QLineEdit *lineEdit = new QLineEdit; lineEdit->setReadOnly(true); lineEdit->setAlignment(Qt::AlignCenter); // 监听lineEdit事件 QLineEdit*lineEdit=newQLineEdit; lineEdit->setReadOnly(true); lineEdit->setAlignment(Qt::AlignCenter); comboBox->setLineEdit(lineEdit); 由https://blog.csdn.net/qq_18286031/article/details/85113931处转载。 void comboBoxInit(QComboBox*box,int widthScroll,int height,bool bClolor) box->setStyle(QStyleFactory::create("windowsvista")); QLineEdit*lineEdit = box->lineEdit(); if(lineEdit == 0) lineEdit = new QL. 字体属性:(font) 大小 {font-size: x-large;}(特大) xx-small;(极小) 一般中文用不到,只要用数值就可以,单位:PX、PD 样式 {font-style: oblique;}(偏斜体) italic;(斜体) normal;(正常) 行高 {line-height: normal;}(正常) 单位:PX、PD、EM 解决方案: 首先从网上找了一下,网上主流方法是通过setLineEdit(QLineEdit *edit)来设置edit的文本居中来完成文本居中显示,这样相当于改变了QComboBox显示框的属性了。但是这样点击edit框会无法弹出下拉框,又需要对edit框进行点击事件处理才可以完成。 我需要正常的label进行显示,尽量不改变它原有的属性,并且可以