1. 程式人生 > >Qt編寫自定義控制元件28-顏色滑塊面板

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:可設定背景顏色

三、效果圖

四、標頭檔案程式碼

#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、學習方法、寫作技巧、熱門技術、職場發展等內容,乾貨多多,