0


QT有关QCobobox控件的样式设置(圆角、下拉框,向上展开、可编辑、内部布局等)

前言

QT设计界面时,难免会遇到修改QCombobox样式的问题。相比于其他的QLabel、QPushButton等控件,QCobobox的样式设置明显困难并复杂很多。以下介绍一下目前为止,本人参考网上代码,制作的一款QCobobox下拉框的样式风格。

效果图:
在这里插入图片描述
在这里插入图片描述

正文

一、基础样式表

/*QCombobox主体*/
QComboBox {
    border:2px solid #f3f3f3;/*设置线宽*/
    background-color:rgb(237,242,255);/*背景颜色*/
    border-radius:15px;/*圆角*/
    padding:1px 2px 1px 2px;/*针对于组合框中的文本内容*/
    text-align:bottom;
    min-width:9em;/*# 组合框的最小宽度*//*min-height: 5em;*/

    border-style:solid;/*边框为实线型*/
    border-width:2px;/*边框宽度*/
    border-color:rgb(77,123,255);/*边框颜色*/

    padding-left:10px;/*左侧边距*/}/*QCombobox右侧按钮*/
QComboBox::drop-down {
    subcontrol-origin: padding;
    subcontrol-position: top right;/*放于右方顶部*/
    width:50px;/*设置按钮范围宽度*//*border-radius: 15px;
    border-left-width: 1px;
    border-left-color: darkgray;
    border-left-style: solid;*/

    border-top-right-radius:3px;/*设置边框圆角*/
    border-bottom-right-radius:3px;/*padding-right: 50px;*/}/*QCombobox右侧按钮的箭头图标*/
QComboBox::down-arrow {
    border-image:url(:/image/down_list.png);/*自定义图片填充*/
    width:10px;/*设置该图标的宽高*/
    height:10px;}/* 下拉后,整个下拉窗体样式 */
QComboBox QAbstractItemView {
    border:2px solid #f3f3f3;/*边框宽度、线形、颜色*/
    background-color:rgba(237,242,255,1);/*背景颜色*/
    border-radius:15px;/*圆角*/
    padding:1px 2px 1px 2px;/*针对于组合框中的文本内容*/
    min-width:9em;/*# 组合框的最小宽度*/}/* 下拉后,整个下拉窗体每项的样式 */
QComboBox QAbstractItemView::item {
    border-radius:15px;/*圆角*/
    height:30px;/* 项的高度(设置pComboBox->setView(new QListView());后,该项才起作用) */
    background-color:rgb(237,242,255);}/*以下部分不知为何不生效,有待调试*//* 下拉后,整个下拉窗体越过每项的样式 */
QComboBox QAbstractItemView::item:hover {
    color: #FFFFF0;/* 整个下拉窗体越过每项的背景色 */
    background-color:rgb(98,0,255);}/* 下拉后,整个下拉窗体被选择的每项的样式 */
QComboBox QAbstractItemView::item:selected {
    color: #FFFFF0;
    background-color:rgb(0,85,200);}

补充:
1.用border-radius: 15px;设置圆角的时候,该控件的高度至少要保证30px,才能显示出圆角,否则为矩形。
2.要在对应的父窗口类初始化代码中,添加setView(new QListView());,下拉框的展开框样式才会生效。

//combobox下拉框样式表生效
    ui->comboBox->setView(newQListView());

问题:
1.下拉框的圆角和透明颜色样式无法实现

/* 下拉后,整个下拉窗体样式 */
QComboBox QAbstractItemView {
    border:2px solid #f3f3f3;/*边框宽度、线形、颜色*/
    background-color:rgba(237,242,255,1);/*背景颜色*/
    border-radius:15px;/*圆角*/
    padding:1px 2px 1px 2px;/*针对于组合框中的文本内容*/
    min-width:9em;/*# 组合框的最小宽度*/}

这个问题,初步猜想是因为展开框属于QWidget,可能需要重新自定义一下这个展开框,对它设置一下可透明属性。(有待验证)

2.可选项的悬浮和选中状态样式未生效

/*以下部分不知为何不生效,有待调试*//* 下拉后,整个下拉窗体越过每项的样式 */
QComboBox QAbstractItemView::item:hover {
    color: #FFFFF0;/* 整个下拉窗体越过每项的背景色 */
    background-color:rgb(98,0,255);}/* 下拉后,整个下拉窗体被选择的每项的样式 */
QComboBox QAbstractItemView::item:selected {
    color: #FFFFF0;
    background-color:rgb(0,85,200);}

3.QCombobox的文本无法居中
之前好像稍微查过,实现起来比较麻烦。成功了的朋友可以在评论区交流一下~~

二、ui designer直接添加可选项

如图:
在这里插入图片描述
这里可以设置icon大小
在这里插入图片描述

三、代码添加可选项

更为常见的,其实是程序在运行过程中,动态对QCombobox填充可选项。比如登录时填充人名数据、选择摄像头分辨率时的分辨率列表等等不固定的元素。
以下是具体操作的代码,有点多但很简单:

//填充下拉选项
    ui->comboBox->clear();//清空combobox
    QStandardItemModel *pItemModel =qobject_cast<QStandardItemModel*>(ui->comboBox->model());//字体设置int combobox_item_fontsize =9;
    QFont font;//font.setPixelSize(combobox_item_fontsize*scale);
    font.setPointSize(combobox_item_fontsize);
    font.setFamily("黑体");//填充默认项(在没有任何数据时,可以先做一个默认的提示项给用户,然后让用户自己输入)
    QString tip_string(u8"请选择用户名");
    ui->comboBox->addItem(tip_string);
    pItemModel->item(0)->setIcon(QIcon(":/image/account.png"));//修改某项图标
    pItemModel->item(0)->setForeground(QColor(255,0,0));//修改某项文本颜色
    pItemModel->item(0)->setBackground(QColor(220,220,220));//修改某项背景颜色
    pItemModel->item(0)->setFont(font);
    pItemModel->item(0)->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);//修改某项文本对齐方式//填充正式项if(ui->comboBox->currentText()== tip_string)
        ui->comboBox->clear();int i=0;
    QStringList m_list;//随便来点填充数据
    m_list<<"AAA"<<"BBB"<<"CCC"<<"DDD";foreach(QString name, m_list){qDebug()<<"combobox additem:"<<name;
        ui->comboBox->addItem(name);

        pItemModel->item(i)->setIcon(QIcon(":/image/account.png"));//修改某项图标//pItemModel->item(i)->setText("修改的文本  " + QString::number(i + 1));                          //修改某项文本//pItemModel->item(i)->setForeground(QColor(255, 0, 0));            //修改某项文本颜色//pItemModel->item(i)->setBackground(QColor(220,220,220));    //修改某项背景颜色(若样式表中已经设置了表项的背景颜色,则不会生效)
        pItemModel->item(i)->setFont(font);
        pItemModel->item(i)->setTextAlignment(Qt::AlignVCenter | Qt::AlignHCenter);//修改某项文本对齐方式
        i++;}//以上设置完,会默认选择第一项。可以手动选择-1项,即为未选择状态//ui->comboBox->setCurrentIndex(-1);

四、下拉框向上展开

有些时候,我们期望QCombobox的下拉框向上展开,例如控件已经来到屏幕下方边缘,若按照原本的向下展开,则被任务栏遮挡一部分。(虽然超出屏幕边缘这种情况,它好像自动会向上展开,不过总有向上展开的需求hh)
方法就是重新自定义一个类,继承QCombobox类,然后重载showPopup();函数

voidshowPopup()override;void myCombox::showPopup(){QComboBox::showPopup();
    QWidget *popup =this->findChild<QFrame*>();//针对当前ui布局,计算QCombobox全局坐标int combobox_y =static_cast<MainWindow *>(this->parent()->parent()->parent()->parent())->y()+static_cast<QWidget *>(this->parent()->parent()->parent())->y()+static_cast<QWidget *>(this->parent()->parent())->y()+static_cast<QWidget *>(this->parent())->y()+this->y();if(popup->y()> combobox_y){
        popup->move(popup->x(),popup->y()-this->height()-popup->height());//x轴不变,y轴向上移动 list的高+combox的高}else{//popup->move(popup->x(),popup->y()-this->height()-popup->height());//x轴不变,y轴向上移动 list的高+combox的高}}

展开的行为就是QComboBox::showPopup();,展开的窗口则是QWidget (所以其实还可以再优化得更好一点)
然后就是对这个窗口的移动。它肯定有一个默认的展开框的默认位置。
逻辑简单来说就是,先计算一下QCombobox的全局y坐标。然后再对比当前实际展开框的y值,判断其是向上展开还是向下展开的。
如果是向下展开,则手动move一下他,y值减少QCombobox的高度和展开框的高度,就能实现向上展开了。

另外,我计算QCombobox全局坐标的时候笨得要死hh,其实还有其他的算法,你们自己尝试吧。

五、详细样式表(编辑模式的状态)

(参考Qt.QComboBox样式表)

/* 未下拉时,QComboBox的样式 */
QComboBox {
    border:1px solid gray;/* 边框 */
    border-radius:3px;/* 圆角 */
    padding:1px 18px 1px 3px;/* 字体填衬 */
    color: #000;
    font: normal normal 15px "Microsoft YaHei";
    background: transparent;}/* 下拉后,整个下拉窗体样式 */
QComboBox QAbstractItemView {
    outline:0px solid gray;/* 选定项的虚框 */
    border:1px solid yellow;/* 整个下拉窗体的边框 */
    color: green;
    background-color: red;/* 整个下拉窗体的背景色 */
    selection-background-color: lightgreen;/* 整个下拉窗体被选中项的背景色 */}/* 下拉后,整个下拉窗体每项的样式 */
QComboBox QAbstractItemView::item {
    height:50px;/* 项的高度(设置pComboBox->setView(new QListView());后,该项才起作用) */}/* 下拉后,整个下拉窗体越过每项的样式 */
QComboBox QAbstractItemView::item:hover {
    color: #FFFFFF;
    background-color: lightgreen;/* 整个下拉窗体越过每项的背景色 */}/* 下拉后,整个下拉窗体被选择的每项的样式 */
QComboBox QAbstractItemView::item:selected {
    color: #FFFFFF;
    background-color: lightgreen;}/* QComboBox中的垂直滚动条 */
QComboBox QAbstractScrollArea QScrollBar:vertical {
    width:10px;
    background-color: #d0d2d4;/* 空白区域的背景色  灰色green */}

QComboBox QAbstractScrollArea QScrollBar::handle:vertical {
    border-radius:5px;/* 圆角 */
    background:rgb(160,160,160);/* 小方块的背景色深灰lightblue */}

QComboBox QAbstractScrollArea QScrollBar::handle:vertical:hover {
    background:rgb(90,91,93);/* 越过小方块的背景色yellow */}/* 设置为可编辑(setEditable(true))editable时,编辑区域的样式 */
QComboBox:editable {
    background: green;}/* 设置为非编辑(setEditable(false))!editable时,整个QComboBox的样式 */
QComboBox:!editable {
     background: blue;}/* 设置为可编辑editable时,点击整个QComboBox的样式 */
QComboBox:editable:on {
    background: green;}/* 设置为非编辑!editable时,点击整个QComboBox的样式 */
QComboBox:!editable:on {
     background: blue;}/* 设置为可编辑editable时,下拉框的样式 */
QComboBox::drop-down:editable {
    background: lightblue;}/* 设置为可编辑editable时,点击下拉框的样式 */
QComboBox::drop-down:editable:on {
    background: lightgreen;}/* 设置为非编辑!editable时,下拉框的样式 */
QComboBox::drop-down:!editable {
    background: lightblue;}/* 设置为非编辑!editable时,点击下拉框的样式 */
QComboBox::drop-down:!editable:on {
    background: lightgreen;}/* 点击QComboBox */
QComboBox:on {}/* 下拉框样式 */
QComboBox::drop-down {
    subcontrol-origin: padding;/* 子控件在父元素中的原点矩形。如果未指定此属性,则默认为padding。 */
    subcontrol-position: top right;/* 下拉框的位置(右上) */
    width:15px;/* 下拉框的宽度 */

    border-left-width:1px;/* 下拉框的左边界线宽度 */
    border-left-color: darkgray;/* 下拉框的左边界线颜色 */
    border-left-style: solid;/* 下拉框的左边界线为实线 */
    border-top-right-radius:3px;/* 下拉框的右上边界线的圆角半径(应和整个QComboBox右上边界线的圆角半径一致) */
    border-bottom-right-radius:3px;/* 同上 */}/* 下拉箭头样式 */
QComboBox::down-arrow {
    width:15px;/* 下拉箭头的宽度(建议与下拉框drop-down的宽度一致) */
    background: transparent;/* 下拉箭头的的背景色 */
    padding:0px 0px 0px 0px;/* 上内边距、右内边距、下内边距、左内边距 */
    image:url(:/images/combobox_arrow_down.png);}/* 点击下拉箭头 */
QComboBox::down-arrow:on {
    image:url(:/images/combobox_arrow_up.png);/* 显示下拉箭头 */}

这个版本他考虑到了编辑模式的状态,而且分得很详细,可以学习一下。

1.遇到的坑
我们知道,如果想要改变QCombobox的字体,只需要setFont()就可以了,也就是

ui->comboBox->setFont(font);

但是当我们选中了可编辑的状态时,往往显示的文本字体却没有发生改变

ui.comboBox->setEditable(true);//此后字体设置无效

这是因为常态的文本显示和可编辑状态下的显示时不一样的,按照我的理解的话,就是一个是内嵌了QLabel显示文本,另一个是内嵌了QLineEdit,用来进行文字的输入。所以这时,我们的修改对象变成了QCombobox的子对象QLineEdit:


ui->comboBox->lineEdit()->setFont(font);

这样的话,才真正响应设置成功

六、QCombobox内部的布局

按照第五步,我才终于意识到原来QCombobox只是一个集合的容器部件,它的里面其实封装了很多其他的东西,所以它才有什么lineedit和qicon什么的嘛。
那么就衍生出了另一种样式设置的方式,那就是直接设置内部的布局,如下:

    QLabel *man =newQLabel(this);
    man->setFixedSize(20*scale,20*scale);
    man->setCursor(QCursor(Qt::ArrowCursor));
    man->setPixmap(QPixmap(":/login/icon_account.png"));
    man->setScaledContents(true);

    QSpacerItem *spaceItem_name =newQSpacerItem(100,10, QSizePolicy::Expanding);
    QHBoxLayout *editLayout_name =newQHBoxLayout();
    editLayout_name->setContentsMargins(14*scale,0,0,0);
    editLayout_name->addWidget(man);
    editLayout_name->addSpacerItem(spaceItem_name);
    ui.comboBox->setLayout(editLayout_name);

如果你有手动代码布局的经验的话,应该能轻松看懂这种设置的方式。我这段代码的话,就是先用QLabel创建一个图标,然后加一条弹簧,在把layout设置进去。用这种做法的话,效果和直接样式表的设置一样,甚至更好更灵活。

比如如果拖拉窗口改变了QCombobox的尺寸,那顺带着也可以改变图标的尺寸了,你不想改变的话就Fix设置定死,但这种方式在跨屏的、不同分辨率底下显示器,需要完美适配的情况下,能够省下不少工作量。

你也可以做成左边图标,中间弹簧,右边下拉箭头的图标,这样只需要在样式表里面设置文本左右的间距,就能完美实现你想要的任何布局了。

标签: qt css 开发语言

本文转载自: https://blog.csdn.net/Larry_Yanan/article/details/123556429
版权归原作者 Larry_Yanan 所有, 如有侵权,请联系我们删除。

“QT有关QCobobox控件的样式设置(圆角、下拉框,向上展开、可编辑、内部布局等)”的评论:

还没有评论