Qt開源作品43-超級圖形字體


一、前言

對於眾多的Qter程序員來說,美化UI一直是個老大難問題,畢竟這種事情理論上應該交給專業的美工妹妹去做,無奈在當前整體國際國內形式之下,絕大部分公司是沒有專門的美工人員的,甚至說有個兼職的美工都已經是很奢侈的事情,大部分的公司都是一個程序員同時要肩負着測試員、美工人員、售后維護人員等人員的責任,老板肯定都是這么想,我花了這么多錢招你進來,所有程序相關的和周邊的你都的給我搞定才行。

程序的UI美化,個人覺得就兩點,第一點就是布局,你必須把控件擺整齊,一定要讓用戶看着舒服,而且用戶操作交互方便,這點在美化UI中占比60%重要,擺的歪歪扭扭,再如何顏色牛逼圖標圖片牛逼也是垃圾,一看就很丑陋,就是拒絕的,你看windows系統就算沒有什么鮮艷的顏色和圖標,各種設置界面都是整整齊齊的,看起來就舒服,才有繼續用下去的可能。第二點才是顏色和圖片,顏色不知道如何配色可以去UI中國等網站找到你喜歡的界面方案,找個拾色器直接把顏色拿過來就行,圖片圖片就需要用到今天的主角圖形字體。

圖形字體的出現絕對是所有程序員的福音,各種類型的各種種類的圖標應有盡有,直接找到你想要的圖標按照值作為文字文本寫進去就行,簡直爽的不要不要的,他是作為文本的形式存在,意味着你可以任意設置大小和顏色,這就不要太強大了哇,我們需要的不就是這種效果嗎?

按照這個思路,在2014年開始就封裝了一個圖形字體類,當初非常簡單,而且重復代碼非常多,今年靜下心來重新封裝重寫了一遍,基本上形成了現在的風格,一個類同時支持多種圖形字體文件(為什么有這個需求?因為網絡上各種圖形字體文件層出不窮,不大方便合並到一個字體文件中,而你的程序又可能都需要使用到這多個圖形字體文件),全部提供靜態方法設置,支持各種導航面板風格。

二、主要功能

  1. 可傳入多種圖形字體文件,一個類通用所有圖形字體。
  2. 默認已經內置了阿里巴巴圖形字體FontAliBaBa、國際知名圖形字體FontAwesome、天氣圖形字體FontWeather。
  3. 可設置 QLabel、QAbstractButton 文本為圖形字體。
  4. 可設置圖形字體作為 QAbstractButton 按鈕圖標。
  5. 內置萬能的方法 getPixmap 將圖形字體值轉換為圖片。
  6. 無論是設置文本、圖標、圖片等都可以設置圖標的大小、尺寸、顏色等參數。
  7. 內置超級導航欄樣式設置,將圖形字體作為圖標設置到按鈕。
  8. 支持各種顏色設置比如正常顏色、懸停顏色、按下顏色、選中顏色。
  9. 可設置導航的位置為 left、right、top、bottom 四種。
  10. 可設置導航加深邊框顏色和粗細大小。
  11. 導航面板的各種切換效果比如鼠標懸停、按下、選中等都自動處理掉樣式設置。
  12. 全局靜態方法,接口豐富,使用極其簡單方便。

三、效果圖


四、開源主頁

  • 以上作品完整源碼下載都在開源主頁,會持續不斷更新作品數量和質量,歡迎各位關注。
  • 本開源項目已經成功升級到V2.0版本,分門別類,圖文並茂,保你爽到爆。
  • Qt開源武林秘籍開發經驗,看完學完,20K起薪,沒有找我!
  1. 國內站點:https://gitee.com/feiyangqingyun/QWidgetDemo
  2. 國際站點:https://github.com/feiyangqingyun/QWidgetDemo
  3. 開源秘籍:https://gitee.com/feiyangqingyun/qtkaifajingyan
  4. 個人主頁:https://qtchina.blog.csdn.net/
  5. 知乎主頁:https://www.zhihu.com/people/feiyangqingyun/

五、核心代碼

QPixmap IconHelper::getPixmap1(const QColor &color, int icon, quint32 size,
                               quint32 width, quint32 height, int flags)
{
    //主動繪制圖形字體到圖片
    QPixmap pix(width, height);
    pix.fill(Qt::transparent);

    QPainter painter;
    painter.begin(&pix);
    painter.setRenderHints(QPainter::Antialiasing | QPainter::TextAntialiasing);
    painter.setPen(color);

    iconFont.setPixelSize(size);
    painter.setFont(iconFont);
    painter.drawText(pix.rect(), flags, (QChar)icon);
    painter.end();
    return pix;
}

void IconHelper::setStyle1(QWidget *widget, QList<QPushButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
{
    QList<QAbstractButton *> list;
    foreach (QPushButton *btn, btns) {
        list << btn;
    }

    setStyle(widget, list, icons, styleColor);
}

void IconHelper::setStyle1(QWidget *widget, QList<QToolButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
{
    QList<QAbstractButton *> list;
    foreach (QToolButton *btn, btns) {
        list << btn;
    }

    setStyle(widget, list, icons, styleColor);
}

void IconHelper::setStyle1(QWidget *widget, QList<QAbstractButton *> btns, QList<int> icons, const IconHelper::StyleColor &styleColor)
{
    int btnCount = btns.count();
    int iconCount = icons.count();
    if (btnCount <= 0 || iconCount <= 0 || btnCount != iconCount) {
        return;
    }

    QString position = styleColor.position;
    quint32 iconSize = styleColor.iconSize;
    quint32 iconWidth = styleColor.iconWidth;
    quint32 iconHeight = styleColor.iconHeight;
    quint32 borderWidth = styleColor.borderWidth;

    //根據不同的位置計算邊框
    QString strBorder;
    if (position == "top") {
        strBorder = QString("border-width:%1px 0px 0px 0px;padding-top:%1px;padding-bottom:%2px;")
                    .arg(borderWidth).arg(borderWidth * 2);
    } else if (position == "right") {
        strBorder = QString("border-width:0px %1px 0px 0px;padding-right:%1px;padding-left:%2px;")
                    .arg(borderWidth).arg(borderWidth * 2);
    } else if (position == "bottom") {
        strBorder = QString("border-width:0px 0px %1px 0px;padding-bottom:%1px;padding-top:%2px;")
                    .arg(borderWidth).arg(borderWidth * 2);
    } else if (position == "left") {
        strBorder = QString("border-width:0px 0px 0px %1px;padding-left:%1px;padding-right:%2px;")
                    .arg(borderWidth).arg(borderWidth * 2);
    }

    //如果圖標是左側顯示則需要讓沒有選中的按鈕左側也有加深的邊框,顏色為背景顏色
    //如果圖標在文字上面而設置的邊框是 top bottom 也需要啟用加深邊框
    QStringList qss;
    if (styleColor.defaultBorder) {
        qss << QString("QWidget[flag=\"%1\"] QAbstractButton{border-style:solid;border-radius:0px;%2border-color:%3;color:%4;background:%5;}")
            .arg(position).arg(strBorder).arg(styleColor.normalBgColor).arg(styleColor.normalTextColor).arg(styleColor.normalBgColor);
    } else {
        qss << QString("QWidget[flag=\"%1\"] QAbstractButton{border-style:none;border-radius:0px;padding:5px;color:%2;background:%3;}")
            .arg(position).arg(styleColor.normalTextColor).arg(styleColor.normalBgColor);
    }

    //懸停+按下+選中
    qss << QString("QWidget[flag=\"%1\"] QAbstractButton:hover{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
        .arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.hoverTextColor).arg(styleColor.hoverBgColor);
    qss << QString("QWidget[flag=\"%1\"] QAbstractButton:pressed{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
        .arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.pressedTextColor).arg(styleColor.pressedBgColor);
    qss << QString("QWidget[flag=\"%1\"] QAbstractButton:checked{border-style:solid;%2border-color:%3;color:%4;background:%5;}")
        .arg(position).arg(strBorder).arg(styleColor.borderColor).arg(styleColor.checkedTextColor).arg(styleColor.checkedBgColor);

    //窗體背景顏色+按鈕背景顏色
    qss << QString("QWidget#%1{background:%2;}")
        .arg(widget->objectName()).arg(styleColor.normalBgColor);
    qss << QString("QWidget>QAbstractButton{border-width:0px;background-color:%1;color:%2;}")
        .arg(styleColor.normalBgColor).arg(styleColor.normalTextColor);
    qss << QString("QWidget>QAbstractButton:hover{background-color:%1;color:%2;}")
        .arg(styleColor.hoverBgColor).arg(styleColor.hoverTextColor);
    qss << QString("QWidget>QAbstractButton:pressed{background-color:%1;color:%2;}")
        .arg(styleColor.pressedBgColor).arg(styleColor.pressedTextColor);
    qss << QString("QWidget>QAbstractButton:checked{background-color:%1;color:%2;}")
        .arg(styleColor.checkedBgColor).arg(styleColor.checkedTextColor);

    //設置樣式表
    widget->setStyleSheet(qss.join(""));

    //可能會重復調用設置所以先要移除上一次的
    for (int i = 0; i < btnCount; i++) {
        for (int j = 0; j < this->btns.count(); j++) {
            if (this->btns.at(j) == btns.at(i)) {
                disconnect(btns.at(i), SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));
                this->btns.at(j)->removeEventFilter(this);
                this->btns.removeAt(j);
                this->pixNormal.removeAt(j);
                this->pixHover.removeAt(j);
                this->pixPressed.removeAt(j);
                this->pixChecked.removeAt(j);
                break;
            }
        }
    }

    //存儲對應按鈕對象,方便鼠標移上去的時候切換圖片
    int checkedIndex = -1;
    for (int i = 0; i < btnCount; i++) {
        int icon = icons.at(i);
        QPixmap pixNormal = getPixmap1(styleColor.normalTextColor, icon, iconSize, iconWidth, iconHeight);
        QPixmap pixHover = getPixmap1(styleColor.hoverTextColor, icon, iconSize, iconWidth, iconHeight);
        QPixmap pixPressed = getPixmap1(styleColor.pressedTextColor, icon, iconSize, iconWidth, iconHeight);
        QPixmap pixChecked = getPixmap1(styleColor.checkedTextColor, icon, iconSize, iconWidth, iconHeight);

        //記住最后選中的按鈕
        QAbstractButton *btn = btns.at(i);
        if (btn->isChecked()) {
            checkedIndex = i;
        }

        btn->setIcon(QIcon(pixNormal));
        btn->setIconSize(QSize(iconWidth, iconHeight));
        btn->installEventFilter(this);
        connect(btn, SIGNAL(toggled(bool)), this, SLOT(toggled(bool)));

        this->btns << btn;
        this->pixNormal << pixNormal;
        this->pixHover << pixHover;
        this->pixPressed << pixPressed;
        this->pixChecked << pixChecked;
    }

    //主動觸發一下選中的按鈕
    if (checkedIndex >= 0) {
        QMetaObject::invokeMethod(btns.at(checkedIndex), "toggled", Q_ARG(bool, true));
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM