在原有项目添加一个新的icon图标

本文指导如何在现有项目中添加新icon,涉及步骤包括:定位旧图标、阿里巴巴矢量图标库下载、本地整合与代码复制。确保正确替换和使用新图标。

第一步 找到原有图标所在的位置

如:
在这里插入图片描述

第二步 在阿里巴巴矢量图标库中下载

图标库地址:https://www.iconfont.cn/

在矢量图标库找到自己要新增加的图标,添加到购物车之后,选择添加至项目
如:
![在这里插入图片描述](https://img-blog.csdnimg.cn/b7b9dc0643214393925a32f7201d007a.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbXVyb25neXV5YW8=,size_9,color_FFFFFF,t_70,g_se,x_16

第三步 到我的项目中点击下载至本地

在这里插入图片描述
下载之后解压,解压完成的目录是这样的:
在这里插入图片描述

第四步 将先下载的代码复制到项目中

1.解压下载下来的压缩包,然后找到iconfont.css这个文件,将@font-face这一段复制到原来的iconfont.css文件中
在这里插入图片描述
还有
在这里插入图片描述

2 然后就是在下面将新图标的类复制过来,也是从新图标的iconfont.svg复制到原来的iconfont.svg中,注意如果新的图标的命名与原来的有冲突的话,自行修改一下,不然就覆盖掉原来的了
将下面的复制到项目icon中的iconfont.svg

<glyph glyph-name="xinxiguanli" unicode="&#59013;" d="M268.8 678.1h401.1V631H268.8v47.1m0-170.6h401.1v-47.2H268.8v47.2m0-169.2h229.3v-47.1H268.8v47.1m712.5-164.7C946.4 231.9 947 233 947 233s-120.6-33.8-143.1 81.8H734S714.7 199 591.5 233.3c-35.6-59.4-36.8-61.2-36.9-61.3 0.1 0 96.5-67.4 0-158.9l37.4-61.5s106.5 45.9 141.4-79.6h70.7s22.2 115.3 141.9 81.2c34.1 58.2 34.7 58.8 34.7 58.8s-90.3 78 0.6 161.6zM767.4-33.1c-69.8 0-126.5 56.6-126.5 126.5s56.6 126.5 126.5 126.5S894 163.3 894 93.4s-56.7-126.5-126.6-126.5zM165.9-77.8c-37.8 0-68.4 30.6-68.4 68.4V774.1c0 37.8 30.6 68.4 68.4 68.4H776c37.8 0 68.4-30.6 68.4-68.4v-411.4H896v448C896 857.8 857.8 896 810.7 896H128C80.9 896 42.7 857.8 42.7 810.7v-853.3c0-47.1 38.2-85.3 85.3-85.3h392.5v50.2H195.9"  horiz-adv-x="1024" />

![在这里插入图片描述](https://img-blog.csdnimg.cn/fb214ee9cc054e209d9a0e8365d8d635.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAbXVyb25neXV5YW8=,size_20,color_FFFFFF,t_70,g_se,x_16

3 上面几步都做完之后,就可以跟其他图标一样,在项目中使用啦。

<think> 为了在QComboBox的显示框左侧添加一个图标,我们可以通过自定义QComboBox的显示方式来实现。通常,我们可以使用QStyledItemDelegate来自定义QComboBox的项(包括当前选中的项和下拉列表中的项)的绘制。但是,如果我们只想在当前选中的显示框(即非下拉状态时)的左侧添加一个图标,我们可以通过重写QComboBox的paintEvent来实现。 另一种更简单的方法是使用QComboBox的setItemIcon方法为每个项设置图标,这样下拉列表中的项也会显示图标。但有时我们可能希望只在下拉列表中显示图标,而当前选中的项不显示;或者反过来,当前选中的项显示图标而下拉列表不显示。这里的要求是只在显示框(当前选中的项)的左侧添加图标,而下拉列表中的项可以没有图标(或者有图标,根据需求而定)。 根据问题,我们需要在显示框的左侧添加一个图标。我们可以考虑以下两种方法: 方法1:为每个项设置图标(使用setItemIcon),这样下拉列表也会显示图标。然后,如果我们希望当前选中的项在显示框中显示图标,那么就会同时显示在下拉列表中。这种方法简单,但可能不符合仅显示框有图标的需求。 方法2:自定义绘制当前选中的显示框。我们可以重写QComboBox的paintEvent,在绘制当前选中的文本之前,先绘制图标。 这里我们使用方法2,因为这样可以更灵活地控制只在显示框(非下拉状态)中绘制图标,而下拉列表中的项不受影响(即下拉列表中的项不显示图标)。 步骤: 1. 创建一个继承自QComboBox的子类。 2. 重写paintEvent方法。 3. 在paintEvent中,先调用基类的paintEvent绘制默认的QComboBox样式(这样可以得到默认的背景、边框等)。 4. 然后计算图标的位置,并在显示框的左侧绘制图标。 但是,直接调用基类的paintEvent会绘制整个控件,包括文本。我们可能需要在绘制文本之前先绘制图标,或者完全自定义绘制过程。然而,为了不破坏原有的样式,我们可以先绘制基类的内容,然后在左边绘制图标,并调整文本的位置。但这样可能会造成文本和图标重叠,因为基类绘制时文本已经绘制了。 另一种做法是完全自定义绘制,但这样比较复杂,需要处理各种状态(如禁用状态、焦点状态等)。因此,我们可以采用以下折中方式: 在绘制完基类的内容后,再在左侧绘制图标,同时将原来的文本向右移动图标的宽度,以避免重叠。但是,由于基类已经绘制了文本,我们无法直接移动它,因此我们需要先擦除原来的文本区域,然后重新绘制文本和图标。 为了避免复杂的绘制,我们可以采用以下方法: 1. 在paintEvent中,我们首先绘制一个图标在左侧。 2. 然后计算文本区域(即整个显示区域减去图标宽度)。 3. 使用QPainter绘制文本,文本区域向右偏移图标宽度。 但是,这样我们就需要自己绘制整个组合框,包括下拉箭头等,这样会丢失样式表设置的样式。 因此,我们可以使用QStyle来绘制组合框的各个部分,然后添加图标和调整文本位置。这样比较复杂。 另一种思路:使用setStyleSheet来设置左侧的图标,通过设置padding-left并添加background-image。但是,这种方法在调整图标位置和大小上可能不够灵活,而且不同平台下样式可能不一致。 综合考虑,我们选择重写paintEvent,并使用QStyle来绘制组合框的背景和箭头,然后自己绘制图标和文本。这样虽然代码多一些,但可以保证样式的一致性。 具体步骤(使用QStyle绘制): 1. 创建QStylePainter。 2. 绘制组合框的框架、箭头等(使用QStyle::CC_ComboBox和QStyleOptionComboBox)。 3. 在绘制文本之前,先绘制图标,然后调整文本的矩形区域,再绘制文本。 示例代码: 我们将创建一个名为IconComboBox的类,继承自QComboBox,并重写paintEvent。 注意:由于需要绘制当前选中的项,我们使用currentIndex()来获取当前索引,然后如果有图标则绘制图标(如果没有设置图标,则使用默认的)。 我们可以提供一个设置图标的方法,例如setDisplayIcon(const QIcon& icon),这样可以为当前显示框设置一个图标(与下拉列表中的项无关)。或者,我们也可以根据当前选中的项来获取图标(如果我们为每个项设置了图标,那么就可以使用itemIcon(currentIndex()))。 这里我们假设我们为每个项设置了图标(通过setItemIcon),但只希望在显示框中显示图标,而下拉列表中使用默认绘制(即不显示图标?)。但是,如果我们通过setItemIcon设置了图标,那么下拉列表默认也会显示图标。所以如果我们希望下拉列表不显示图标,就需要自定义下拉列表的绘制(通过设置item delegate)。这会使问题复杂化。 因此,我们改变需求:我们只关心显示框(当前选中的项)的左侧有图标,而下拉列表中的项我们不做要求(可以显示图标也可以不显示)。如果希望下拉列表不显示图标,那么我们可以设置一个delegate来绘制下拉列表,但这里我们先不考虑。 这里我们只重写paintEvent,在显示框中绘制图标,并且如果下拉列表中的项有图标,我们也不在下拉列表中显示(因为下拉列表的绘制由delegate负责,而默认的delegate会绘制图标)。如果我们希望下拉列表不绘制图标,那么我们需要设置一个自定义的delegate,在绘制下拉项时不绘制图标。 为了简单,我们只处理显示框的图标。 具体步骤(在paintEvent中): 1. 创建QStylePainter用于绘制组合框。 2. 创建QStyleOptionComboBox对象,并初始化。 3. 绘制组合框的背景和箭头(使用QStyle::CE_ComboBoxLabel绘制标签部分?或者使用QStyle::CC_ComboBox绘制整个控件?) 4. 计算图标的绘制位置(通常是在显示区域的左侧,垂直居中)。 5. 绘制图标。 6. 调整文本的绘制区域(在图标右侧),然后绘制文本。 但是,QStyle::drawComplexControl(QStyle::CC_ComboBox, opt)会绘制整个组合框,包括按钮和框架。然后我们可以在标签区域绘制图标和文本。 然而,更精细的做法是: - 使用QStyle::CC_ComboBox绘制框架和下拉箭头。 - 然后使用QStyle::SC_ComboBoxEditField获取编辑字段的区域。 - 在这个编辑字段区域内,我们绘制图标和文本。 示例代码: 注意:以下代码只处理显示框(当前选中的项)的绘制,下拉列表的绘制不受影响(即下拉列表的项如果设置了图标,默认会显示;如果不想显示,需要另外设置delegate)。 我们开始编写代码: 头文件 IconComboBox.h ```cpp #include <QComboBox> #include <QPainter> #include <QStyleOptionComboBox> #include <QStylePainter> class IconComboBox : public QComboBox { Q_OBJECT public: explicit IconComboBox(QWidget *parent = nullptr); protected: void paintEvent(QPaintEvent *e) override; }; ``` 源文件 IconComboBox.cpp ```cpp #include "IconComboBox.h" IconComboBox::IconComboBox(QWidget *parent) : QComboBox(parent) { } void IconComboBox::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QStylePainter painter(this); painter.setPen(palette().color(QPalette::Text)); // 绘制组合框的框架和下拉箭头 QStyleOptionComboBox opt; initStyleOption(&opt); // 绘制整个组合框(但不绘制文本和图标,因为我们要自定义) painter.drawComplexControl(QStyle::CC_ComboBox, opt); // 获取编辑区域(用于绘制文本和图标的区域) QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); painter.drawText(editRect, Qt::AlignLeft | Qt::AlignVCenter, "Test"); // 仅用于测试 // 但是,上面的drawText会直接绘制文本,我们需要先绘制图标,然后绘制文本(偏移) // 获取当前项的图标 QIcon icon = this->itemIcon(currentIndex()); if (!icon.isNull()) { // 设置图标大小,这里使用editRect的高度-4作为图标边长(保持一些边距) int iconSize = editRect.height() - 4; QRect iconRect = editRect; iconRect.setWidth(iconSize); iconRect.adjust(2, 2, 0, -2); // 上下各留2像素边距 // 绘制图标 icon.paint(&painter, iconRect, Qt::AlignCenter); // 调整文本区域,使其从图标右侧开始 editRect.adjust(iconSize + 4, 0, 0, 0); // 图标和文本之间留4像素 } // 绘制文本 // 注意:如果文本过长,需要省略号,我们可以使用painter的字体规格来计算 painter.drawText(editRect, Qt::AlignLeft | Qt::AlignVCenter, this->currentText()); } ``` 然而,上面的代码有一个问题:我们调用了两次绘制文本(第一次测试绘制了一次,然后后面又绘制了一次)。所以我们需要去掉测试绘制。 另外,我们直接使用了当前项的图标(itemIcon(currentIndex()))。这样,如果当前项没有设置图标,则不会绘制图标。 但是,我们可能希望为组合框设置一个单独的图标(与项无关),那么我们可以添加一个成员变量来存储这个图标,并在paintEvent中使用它。 修改后的版本: 头文件添加: ```cpp private: QIcon m_displayIcon; public: void setDisplayIcon(const QIcon &icon); ``` 源文件实现setDisplayIcon: ```cpp void IconComboBox::setDisplayIcon(const QIcon &icon) { m_displayIcon = icon; update(); // 触发重绘 } ``` 然后在paintEvent中,我们可以这样: ```cpp // 获取图标:优先使用m_displayIcon,如果没有则使用当前项的图标 QIcon icon = m_displayIcon; if (icon.isNull()) { icon = this->itemIcon(currentIndex()); } ``` 完整代码: 头文件 IconComboBox.h ```cpp #ifndef ICONCOMBOBOX_H #define ICONCOMBOBOX_H #include <QComboBox> #include <QIcon> class IconComboBox : public QComboBox { Q_OBJECT public: explicit IconComboBox(QWidget *parent = nullptr); void setDisplayIcon(const QIcon &icon); protected: void paintEvent(QPaintEvent *e) override; private: QIcon m_displayIcon; }; #endif // ICONCOMBOBOX_H ``` 源文件 IconComboBox.cpp ```cpp #include "IconComboBox.h" #include <QPainter> #include <QStyleOptionComboBox> #include <QStylePainter> IconComboBox::IconComboBox(QWidget *parent) : QComboBox(parent) { } void IconComboBox::setDisplayIcon(const QIcon &icon) { m_displayIcon = icon; update(); // 触发重绘 } void IconComboBox::paintEvent(QPaintEvent *e) { Q_UNUSED(e); QStylePainter painter(this); painter.setPen(palette().color(QPalette::Text)); // 绘制组合框的框架和下拉箭头 QStyleOptionComboBox opt; initStyleOption(&opt); // 绘制整个组合框的框架和下拉箭头 painter.drawComplexControl(QStyle::CC_ComboBox, opt); // 获取编辑区域(用于绘制文本和图标的区域) QRect editRect = style()->subControlRect(QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this); // 获取图标:优先使用m_displayIcon,如果没有则使用当前项的图标 QIcon icon = m_displayIcon; if (icon.isNull()) { icon = this->itemIcon(currentIndex()); } if (!icon.isNull()) { // 设置图标大小,这里使用editRect的高度-4作为图标边长(保持一些边距) int iconSize = editRect.height() - 4; // 如果图标大小小于等于0,则跳过 if (iconSize > 0) { QRect iconRect(editRect.x() + 2, editRect.y() + 2, iconSize, iconSize); // 绘制图标 icon.paint(&painter, iconRect, Qt::AlignCenter); // 调整文本区域,使其从图标右侧开始 editRect.setLeft(iconRect.right() + 4); // 图标右侧留4像素空白 } } // 绘制文本 // 如果文本过长,使用省略号 QString text = this->currentText(); int textFlags = Qt::AlignLeft | Qt::AlignVCenter; // 使用字体规格,如果文本过长则省略 QFontMetrics fm = painter.fontMetrics(); text = fm.elidedText(text, Qt::ElideRight, editRect.width()); painter.drawText(editRect, textFlags, text); } ``` 这样,我们就实现了在显示框左侧显示图标的功能。如果设置了setDisplayIcon,则使用这个图标;否则,使用当前项的图标(如果有的话)。 注意:如果既没有设置displayIcon,当前项也没有图标,那么就不绘制图标。 此外,我们还处理了文本过长的情况,使用省略号。 但是,我们可能还需要考虑组合框的禁用状态,以及图标的状态(禁用时变灰)。在绘制图标时,我们可以根据组合框的状态来设置图标的模式(mode)和状态(state)。 修改图标绘制部分: ```cpp QIcon::Mode mode = isEnabled() ? QIcon::Normal : QIcon::Disabled; QIcon::State state = hasFocus() ? QIcon::On : QIcon::Off; icon.paint(&painter, iconRect, Qt::AlignCenter, mode, state); ``` 这样,在禁用状态下,图标会变灰。 最后,我们使用这个自定义的IconComboBox: ```cpp IconComboBox *combo = new IconComboBox(this); combo->addItem("Option 1"); combo->addItem("Option 2"); combo->setDisplayIcon(QIcon(":/icon.png")); // 设置显示图标 // 或者为每个项设置图标 // combo->setItemIcon(0, QIcon(":/icon1.png")); // combo->setItemIcon(1, QIcon(":/icon2.png")); ``` 注意:如果同时使用setDisplayIcon和setItemIcon,那么setDisplayIcon有优先权。 以上代码提供了一个基本的实现,但可能在某些样式下需要调整边距和位置。 相关问题: §§相关问题§§: 1. 在Qt中,如何自定义QComboBox的下拉列表项的绘制? 2. 如何使用QStyledItemDelegate来自定义QComboBox的项? 3. 在自定义控件的paintEvent中,为什么要使用QStylePainter而不是普通的QPainter? 4. 如何使QComboBox的文本在图标旁边垂直居中? </think> 在Qt中,重写`QComboBox`以在显示框左侧添加图标,可以通过自定义控件的绘制事件实现。以下是完整的解决方案: ### 解决方案代码 ```cpp #include <QComboBox> #include <QPainter> #include <QStyleOptionComboBox> class IconComboBox : public QComboBox { Q_OBJECT public: explicit IconComboBox(QWidget *parent = nullptr) : QComboBox(parent) {} // 设置显示框左侧图标 void setDisplayIcon(const QIcon &icon) { m_icon = icon; update(); // 触发重绘 } protected: void paintEvent(QPaintEvent *event) override { Q_UNUSED(event); QStylePainter painter(this); painter.setPen(palette().color(QPalette::Text)); // 1. 绘制基础控件框架 QStyleOptionComboBox opt; initStyleOption(&opt); painter.drawComplexControl(QStyle::CC_ComboBox, opt); // 2. 获取内容绘制区域 QRect textRect = style()->subControlRect( QStyle::CC_ComboBox, &opt, QStyle::SC_ComboBoxEditField, this ); // 3. 绘制左侧图标 if (!m_icon.isNull()) { // 计算图标位置(左侧居中) int iconSize = qMin(textRect.height() - 4, 16); // 图标大小 QRect iconRect(textRect.x() + 2, textRect.y() + (textRect.height() - iconSize)/2, iconSize, iconSize); // 根据控件状态设置图标模式 QIcon::Mode mode = isEnabled() ? QIcon::Normal : QIcon::Disabled; m_icon.paint(&painter, iconRect, Qt::AlignCenter, mode); // 调整文本区域起始位置(图标右侧) textRect.setX(iconRect.right() + 4); } // 4. 绘制文本内容 QString text = currentText(); // 添加省略号防止文本过长 text = painter.fontMetrics().elidedText(text, Qt::ElideRight, textRect.width()); // 绘制居中对齐的文本 int flags = Qt::AlignLeft | Qt::AlignVCenter; painter.drawText(textRect, flags, text); } private: QIcon m_icon; // 存储左侧图标 }; ``` ### 使用示例 ```cpp // 创建自定义组合框 IconComboBox *combo = new IconComboBox(this); combo->addItems({"Option 1", "Option 2", "Option 3"}); // 设置左侧图标(使用资源路径或文件路径) combo->setDisplayIcon(QIcon(":/icons/icon.png")); // 添加到布局 layout->addWidget(combo); ``` ### 原理解释 1. **自定义绘制流程**: - 继承`QComboBox`并重写`paintEvent` - 使用`QStylePainter`确保遵循当前系统主题 - 分三步绘制:控件框架 → 图标 → 文本 2. **图标定位关键点**: ```cpp // 计算垂直居中位置 QRect iconRect(textRect.x() + 2, textRect.y() + (textRect.height() - iconSize)/2, iconSize, iconSize); ``` - `+2` 添加左侧内边距 - `(height - iconSize)/2` 实现垂直居中 3. **文本区域调整**: ```cpp textRect.setX(iconRect.right() + 4); // 图标后留4px间距 ``` 避免文本与图标重叠 4. **状态处理**: ```cpp QIcon::Mode mode = isEnabled() ? Normal : Disabled; ``` 根据控件启用状态自动切换图标显示模式 ### 注意事项 1. **图标尺寸**:示例使用`16px`作为最大尺寸,可根据实际需求调整 2. **样式兼容**:通过`QStyle`方法获取绘制区域,确保兼容不同系统主题 3. **性能优化**:只在图标变化时调用`update()`,避免不必要的重绘
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值