天天看點

Qt編寫自定義控件28-顔色滑塊面闆

一、前言

相比于上一個顔色按鈕面闆,此控件就要難很多,顔色值有三種表示形式,除了程式員最常用的RGB以外,還有HSB和CMY方式。

RGB色彩模式是工業界的一種顔色标準,是通過對紅(R)、綠(G)、藍(B)三個顔色通道的變化以及它們互相之間的疊加來得到各式各樣的顔色的,RGB即是代表紅、綠、藍三個通道的顔色,這個标準幾乎包括了人類視力所能感覺的所有顔色,是目前運用最廣的顔色系統之一。也是程式員最喜歡最常用的顔色表示方法。

HSB又稱HSV,表示一種顔色模式:在HSB模式中,H(hues)表示色相,S(saturation)表示飽和度,B(brightness)表示亮度HSB模式對應的媒介是人眼。HSB模式中S和B呈現的數值越高,飽和度明度越高,頁面色彩強烈豔麗,對視覺刺激是迅速的,醒目的效果,但不益于長時間的觀看。

CMY是青(Cyan)、洋紅或品紅(Magenta)和黃(Yellow)三種顔色的簡寫,是相減混色模式,用這種方法産生的顔色之是以稱為相減色,乃是因為它減少了為視覺系統識别顔色所需要的反射光。

由于本控件用于燈光舞台效果的控制控件,可能使用者不一定相關使用RGB顔色,也可能用到HSB或者CMY,是以在提供顔色選擇的時候,三種都要提供,一種處于選中調節模式的情況下,另外兩種要跟随變化,這個是難點,要不斷計算目前的顔色值換算成其他顔色值,一開始采用了各種公式換算,後面發現原來QColor内部就封裝了,我擦,比如QColor::fromHsv,QColor::fromRgb等,真的是非常強大,可以不用管具體的換算細節。

二、實作的功能

  • 1:可設定滑塊條之間的間隔
  • 2:可設定滑塊組之間的間隔
  • 3:可設定背景顔色

三、效果圖

Qt編寫自定義控件28-顔色滑塊面闆

四、頭檔案代碼

#ifndef COLORPANELFADER_H
#define COLORPANELFADER_H

/**
 * 顔色滑塊面闆 作者:feiyangqingyun(QQ:517216493) 2017-11-17
 * 1:可設定滑塊條之間的間隔
 * 2:可設定滑塊組之間的間隔
 * 3:可設定背景顔色
 */

#include <QWidget>

class QHBoxLayout;
class QSpacerItem;
class ColorPanelBar;

#ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif

class QDESIGNER_WIDGET_EXPORT ColorPanelFader : public QWidget
#else
class ColorPanelFader : public QWidget
#endif

{
    Q_OBJECT
    Q_PROPERTY(int barSpace READ getBarSpace WRITE setBarSpace)
    Q_PROPERTY(int groupSpace READ getGroupSpace WRITE setGroupSpace)
    Q_PROPERTY(QColor bgColor READ getBgColor WRITE setBgColor)

public:
    explicit ColorPanelFader(QWidget *parent = 0);

protected:
    bool eventFilter(QObject *watched, QEvent *event);
    void paintEvent(QPaintEvent *);

private:
    QHBoxLayout *layout;
    QSpacerItem *spacer1;
    QSpacerItem *spacer2;
    QList<ColorPanelBar *> items;

    int barSpace;               //柱狀條間隔
    int groupSpace;             //分組間隔
    QColor bgColor;             //背景顔色

private slots:
    void colorChanged(const QColor &color, double value, double percent);

public:
    int getBarSpace()           const;
    int getGroupSpace()         const;
    QColor getBgColor()         const;

    QSize sizeHint()            const;
    QSize minimumSizeHint()     const;

public:
    //設定柱狀條間隔
    void setBarSpace(int barSpace);
    //設定分組間隔
    void setGroupSpace(int groupSpace);
    //設定背景顔色
    void setBgColor(const QColor &bgColor);

Q_SIGNALS:
    void colorChanged(const QColor &color, double hue, double sat, double bright);
};

#endif // COLORPANELFADER_H

           

五、核心代碼

bool ColorPanelFader::eventFilter(QObject *watched, QEvent *event)
{
    if (event->type() == QEvent::MouseButtonPress) {
        ColorPanelBar *item = (ColorPanelBar *)watched;
        int index = items.indexOf(item);
        if (index >= 6) {
            items.at(0)->setEnabled(false);
            items.at(1)->setEnabled(false);
            items.at(2)->setEnabled(false);
            items.at(3)->setEnabled(false);
            items.at(4)->setEnabled(false);
            items.at(5)->setEnabled(false);
        } else if (index >= 3) {
            items.at(0)->setEnabled(false);
            items.at(1)->setEnabled(false);
            items.at(2)->setEnabled(false);
            items.at(6)->setEnabled(false);
            items.at(7)->setEnabled(false);
            items.at(8)->setEnabled(false);
        } else if (index >= 0) {
            items.at(3)->setEnabled(false);
            items.at(4)->setEnabled(false);
            items.at(5)->setEnabled(false);
            items.at(6)->setEnabled(false);
            items.at(7)->setEnabled(false);
            items.at(8)->setEnabled(false);
        }
    } else if (event->type() == QEvent::MouseButtonRelease) {
        ColorPanelBar *item = (ColorPanelBar *)watched;
        int index = items.indexOf(item);
        if (index >= 6) {
            items.at(0)->setEnabled(true);
            items.at(1)->setEnabled(true);
            items.at(2)->setEnabled(true);
            items.at(3)->setEnabled(true);
            items.at(4)->setEnabled(true);
            items.at(5)->setEnabled(true);
        } else if (index >= 3) {
            items.at(0)->setEnabled(true);
            items.at(1)->setEnabled(true);
            items.at(2)->setEnabled(true);
            items.at(6)->setEnabled(true);
            items.at(7)->setEnabled(true);
            items.at(8)->setEnabled(true);
        } else if (index >= 0) {
            items.at(3)->setEnabled(true);
            items.at(4)->setEnabled(true);
            items.at(5)->setEnabled(true);
            items.at(6)->setEnabled(true);
            items.at(7)->setEnabled(true);
            items.at(8)->setEnabled(true);
        }
    }

    return QWidget::eventFilter(watched, event);
}

void ColorPanelFader::paintEvent(QPaintEvent *)
{
    QPainter painter(this);
    painter.fillRect(rect(), bgColor);
}

void ColorPanelFader::colorChanged(const QColor &color, double value, double percent)
{
    ColorPanelBar *item = (ColorPanelBar *)sender();
    int index = items.indexOf(item);

    if (index == 0) {
        //擷取目前HSB處的顔色值
        items.at(1)->setTopColor(color);
        items.at(2)->setTopColor(color);
        items.at(1)->setBorderColor(color);
        items.at(2)->setBorderColor(color);
    } else if (index == 1) {
        items.at(2)->setTopColor(color);
        items.at(2)->setBorderColor(color);
    } else if (index == 2) {
        items.at(1)->setTopColor(color);
        items.at(1)->setBorderColor(color);
    } else if (index == 3) {
        items.at(6)->setPercent(100 - percent);
    } else if (index == 4) {
        items.at(7)->setPercent(100 - percent);
    } else if (index == 5) {
        items.at(8)->setPercent(100 - percent);
    } else if (index == 6) {
        items.at(3)->setPercent(100 - percent);
    } else if (index == 7) {
        items.at(4)->setPercent(100 - percent);
    } else if (index == 8) {
        items.at(5)->setPercent(100 - percent);
    }

    //如果是HSB變化則CMY和RGB變化
    if (index < 3) {
        double hue = items.at(0)->getPercent() / 100;
        double sat = items.at(1)->getPercent() / 100;
        double bright = items.at(2)->getPercent() / 100;

        //組合HSB目前值,然後轉為CMY和RGB計算百分比進行設定
        QColor color = QColor::fromHsvF(hue, sat, bright);
        double percentRed = color.redF() * 100;
        double percentGreen = color.greenF() * 100;
        double percentBlue = color.blueF() * 100;

        items.at(3)->setPercent(100 - percentRed);
        items.at(4)->setPercent(100 - percentGreen);
        items.at(5)->setPercent(100 - percentBlue);
        items.at(6)->setPercent(percentRed);
        items.at(7)->setPercent(percentGreen);
        items.at(8)->setPercent(percentBlue);
    }

    //根據百分比擷取顔色值
    double red = items.at(6)->getPercent() / 100;
    double green = items.at(7)->getPercent() / 100;
    double blue = items.at(8)->getPercent() / 100;
    QColor currentColor = QColor::fromRgbF(red, green, blue);
    emit colorChanged(currentColor, items.at(0)->getValue(), items.at(1)->getPercent(), items.at(2)->getPercent());

    //如果是CMY或者RGB變化則HSB變化
    if (index >= 3) {
        //hue活出現負數=白色,要矯正
        double percentHue = currentColor.hueF() * 100;
        if (percentHue < 0) {
            percentHue = 0;
        }

        double percentSat = currentColor.saturationF() * 100;
        double percentBright = currentColor.lightnessF() * 100;

        //計算目前值所占百分比
        items.at(0)->setPercent(percentHue);
        items.at(1)->setPercent(percentSat);
        items.at(2)->setPercent(percentBright);

        items.at(1)->setTopColor(currentColor);
        items.at(2)->setTopColor(currentColor);
        items.at(1)->setBorderColor(currentColor);
        items.at(2)->setBorderColor(currentColor);
    }
}
           

六、控件介紹

  1. 超過149個精美控件,涵蓋了各種儀表盤、進度條、進度球、指南針、曲線圖、标尺、溫度計、導覽列、導航欄,flatui、高亮按鈕、滑動選擇器、農曆等。遠超qwt內建的控件數量。
  2. 每個類都可以獨立成一個單獨的控件,零耦合,每個控件一個頭檔案和一個實作檔案,不依賴其他檔案,友善單個控件以源碼形式內建到項目中,較少代碼量。qwt的控件類環環相扣,高度耦合,想要使用其中一個控件,必須包含所有的代碼。
  3. 全部純Qt編寫,QWidget+QPainter繪制,支援Qt4.6到Qt5.12的任何Qt版本,支援mingw、msvc、gcc等編譯器,支援任意作業系統比如windows+linux+mac+嵌入式linux等,不亂碼,可直接內建到Qt Creator中,和自帶的控件一樣使用,大部分效果隻要設定幾個屬性即可,極為友善。
  4. 每個控件都有一個對應的單獨的包含該控件源碼的DEMO,友善參考使用。同時還提供一個所有控件使用的內建的DEMO。
  5. 每個控件的源代碼都有詳細中文注釋,都按照統一設計規範編寫,友善學習自定義控件的編寫。
  6. 每個控件預設配色和demo對應的配色都非常精美。
  7. 超過130個可見控件,6個不可見控件。
  8. 部分控件提供多種樣式風格選擇,多種訓示器樣式選擇。
  9. 所有控件自适應窗體拉伸變化。
  10. 內建自定義控件屬性設計器,支援拖曳設計,所見即所得,支援導入導出xml格式。
  11. 自帶activex控件demo,所有控件可以直接運作在ie浏覽器中。
  12. 內建fontawesome圖形字型+阿裡巴巴iconfont收藏的幾百個圖形字型,享受圖形字型帶來的樂趣。
  13. 所有控件最後生成一個dll動态庫檔案,可以直接內建到qtcreator中拖曳設計使用。
  14. 目前已經有qml版本,後期會考慮出pyqt版本,如果使用者需求量很大的話。

七、SDK下載下傳

  • SDK下載下傳連結: https://pan.baidu.com/s/1A5Gd77kExm8Co5ckT51vvQ 提取碼:877p
  • 下載下傳連結中包含了各個版本的動态庫檔案,所有控件的頭檔案,使用demo,自定義控件+屬性設計器。
  • 自定義控件插件開放動态庫dll使用(永久免費),無任何後門和限制,請放心使用。
  • 目前已提供26個版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
  • 不定期增加控件和完善控件,不定期更新SDK,歡迎各位提出建議,謝謝!
  • widget版本(QQ:517216493)qml版本(QQ:373955953)三峰駝(QQ:278969898)。
  • 濤哥的知乎專欄 Qt進階之路 https://zhuanlan.zhihu.com/TaoQt
  • 歡迎關注微信公衆号【高效程式員】,C++/Python、學習方法、寫作技巧、熱門技術、職場發展等内容,幹貨多多,福利多多!

繼續閱讀