图标字体生成及Qt使用

1 准备

需要准备的软件

  • 浏览器:用于图标的下载及图标字体的生成
  • vs code:用于编辑一些文本文档
  • Qt:编写程序,显示图标字体中的图标

2 图标字体的生成

2.1 准备图标

要生成图标字体,首先需要准备图标集(单个图标也没有必要生成图标字体,直接在Qt中使用就行)
以下有几个网站,可用于下载图标。关于这几个网站,详细可以去问AI,这里就不具体介绍了。笔者这里选择了第一个Remix Icon。

如下图,只下载svg即可
Pasted image 20250803003036

下载解压后,可以看到有很多文件夹,我这里将文件夹中所有的svg图标放在一个目录中

Pasted image 20250804190902

后面也可以随时补充svg图片

2.2 字体生成

打开字体生成网站,笔者这里选择IcoMoon,当然也可以选择其他的。
选择IconMoon App,进入图标字体工程界面

Pasted image 20250804191156

点击“Import”,选中所有的svg图片,然后导入

Pasted image 20250804191429

导入成功后,点击下图中右侧按钮,会弹出一个菜单,可以管理和设置这些图标的一些属性

Pasted image 20250804191541

设置成功后,点击右下角的Generate Font进入图标生成界面

Pasted image 20250804191620

此时,右下角会出现download和一个设置按钮,先点设置按钮

Pasted image 20250804191847

以下是我的配置:

Pasted image 20250804191929

设置好后,点击download下载即可。下载成功后,将压缩包解压,可以看到有以下文件

Pasted image 20250804192307

*.ttf格式的字体文件和selection.json拷贝出来,接下来将利用selection.json文件中的信息生成字体中所有图标的地址枚举变量(C/C++)

3 生成图标地址枚举(C/C++)

接下来就需要编写Qt程序,解析json文件,生成所有图标对应地址的枚举变量,先说明下使用:

使用说明

  • 首先配置ttf文件、json文件路径,以及输出路径
  • 生成的枚举变量也需要进行命名,笔者这里还套了一层namespace,格式自定义就好,但一定要保留[fill],后续[fill]将会被枚举值替换。
  • 点击生成,即可生成所有图标对应的枚举信息,并且会将图标显示出来,选中图标后还会显示图标的枚举变量名和对应的地址值。

Pasted image 20250804193921

关键程序:json的解析

观察json文件就能找出下面的规律,在icons对应的jsonArray中,对于每个icon对象,有properties的对象,然后有name和code属性。name属性就是枚举名称,code属性就是地址。

{
  "IcoMoonType": "selection",
  "icons": [
    {
      "icon": {
        "paths": [
          "M469.333 469.333v85.333l-227.304 256h227.304v85.333h-341.333v-85.333l227.224-256h-227.224v-85.333h341.333zM896 128v85.333l-227.302 256h227.302v85.333h-341.333v-85.333l227.226-256h-227.226v-85.333h341.333z"
        ],
        "attrs": [
          {}
        ],
        "isMulticolor": false,
        "isMulticolor2": false,
        "grid": 0,
        "tags": [
          "zzz-line"
        ]
      },
      "attrs": [
        {}
      ],
      "properties": {
        "order": 4242,
        "id": 0,
        "name": "zzz-line",
        "prevSize": 128,
        "code": 62705
      },
      "setIdx": 0,
      "setId": 0,
      "iconIdx": 3057
    }
  ],
}

下面为提取的关键代码,输入为json文件的所有内容,输出为枚举名和枚举地址,即填充[fill]中的内容。

void MainWindow::process(const QByteArray &jsonByteArray, QStringList &outList)
{
    QJsonDocument doc = QJsonDocument::fromJson(jsonByteArray);
    QJsonArray jsonArray = doc.object().value("icons").toArray();

    auto processName = [](const QString &name){
        QRegularExpression numRegex("^\\d+$");
        if (numRegex.match(name).hasMatch()) {
            return QString("Num0%1").arg(name);
        }
        // 处理非数字情况:分割连字符并转为驼峰式
        QStringList parts = name.split('-', Qt::SkipEmptyParts);
        QString result;
        for (const QString &part : parts) {
            if (!part.isEmpty()) {
                // 首字母大写,其余小写
                QString formatted = part.left(1).toUpper();
                if (part.size() > 1) {
                    formatted += part.mid(1).toLower();
                }
                result += formatted;
            }
        }
        return result;
    };

    foreach (QJsonValue value, jsonArray) {
        QJsonObject rootObj = value.toObject();
        QJsonObject propObj = rootObj.value("properties").toObject();
        QString name = propObj.value("name").toString();
        //处理名字
        name = processName(name);

        int addr = propObj.value("code").toInt();
        QString lineStr = QString("\t%1 = 0x%2").arg(name).arg(QString::number(addr,16).toUpper());
        outList.append(lineStr);
    }
}

图中tabwidget中图标的显示

首先,需要将*.ttf格式的字体加入QFontDatabase中进行管理

int fontId = QFontDatabase::addApplicationFont(ttfFile);
if(fontId<0) return;
QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);    //获取字体族 名

使用时,先设置字体,然后填入地址访问即可

QFont font;
font.setFamily(fontFamilies.at(0));
font.setPointSize(20);

//QTableWidgetItem
QTableWidgetItem *item = new QTableWidgetItem;
ui->tableWidget->setItem(i,j,item);
item->setFont(font);
item->setText(QChar(addr)); 

完整代码:

void MainWindow::openIcon(const QString &ttfFile, const QStringList &keyValue)
{
    int fontId = QFontDatabase::addApplicationFont(ttfFile);
    if(fontId<0) return;
    QStringList fontFamilies = QFontDatabase::applicationFontFamilies(fontId);

    ui->tableWidget->clear();

    int colCount = 4;
    int rowCount = keyValue.count()/colCount;
    if(keyValue.count()%rowCount){
        rowCount++;
    }
    ui->tableWidget->setColumnCount(colCount);
    ui->tableWidget->setRowCount(rowCount);

    // 创建字体
    QFont font;
    font.setFamily(fontFamilies.at(0));
    font.setPointSize(20);
    int count = 0;
    foreach (QString key, keyValue) {
        key.remove("\t");
        QStringList list = key.split("=");
        if(list.count()<2) continue;
        QString addrStr = list.at(1);
        addrStr.remove(" ");
        bool ok;
        int addr = addrStr.toInt(&ok,16);
        if(!ok) continue;

        int i = count / colCount;
        int j = count % colCount;
        QTableWidgetItem *item = new QTableWidgetItem;
        ui->tableWidget->setItem(i,j,item);
        item->setFont(font);
        item->setText(QChar(addr));

        key.replace("=",":");
        item->setToolTip(key);
        item->setData(Qt::UserRole+1,key);
        count++;
    }
}

图标的使用

方式1:生成QIcon

	//设置字体
	QFont font;
    font.setFamily("XNormalIcon");
    font.setPointSize(20);
    //生成pixmap
    QPixmap pixmap(32,32);
    pixmap.fill(Qt::transparent); // 透明背景
    QPainter painter(&pixmap);
    painter.setFont(font);
    painter.setPen(Qt::blue);
    painter.drawText(pixmap.rect(), Qt::AlignCenter, QChar(SCFont::AccessibilityFill));
    painter.end();
    //生成icon
    QIcon icon(pixmap);

方式二:对于一些可以setText的控件

先设置字体,然后setText即可

	QFont font;
    font.setFamily("XNormalIcon");
    font.setPointSize(20);
    QLabel *label = new QLabel;
    label->setFont(font);
    label->setText(QChar(SCFont::AccessibilityFill));
posted @ 2025-08-04 21:21  光头就不会掉头发了吧  阅读(88)  评论(0)    收藏  举报