一、前言
相比於上一個顏色按鈕面板,此控件就要難很多,顏色值有三種表示形式,除了程序員最常用的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);
}
}
六、控件介紹
- 超過149個精美控件,涵蓋了各種儀表盤、進度條、進度球、指南針、曲線圖、標尺、溫度計、導航條、導航欄,flatui、高亮按鈕、滑動選擇器、農歷等。遠超qwt集成的控件數量。
- 每個類都可以獨立成一個單獨的控件,零耦合,每個控件一個頭文件和一個實現文件,不依賴其他文件,方便單個控件以源碼形式集成到項目中,較少代碼量。qwt的控件類環環相扣,高度耦合,想要使用其中一個控件,必須包含所有的代碼。
- 全部純Qt編寫,QWidget+QPainter繪制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等編譯器,支持任意操作系統比如windows+linux+mac+嵌入式linux等,不亂碼,可直接集成到Qt Creator中,和自帶的控件一樣使用,大部分效果只要設置幾個屬性即可,極為方便。
- 每個控件都有一個對應的單獨的包含該控件源碼的DEMO,方便參考使用。同時還提供一個所有控件使用的集成的DEMO。
- 每個控件的源代碼都有詳細中文注釋,都按照統一設計規范編寫,方便學習自定義控件的編寫。
- 每個控件默認配色和demo對應的配色都非常精美。
- 超過130個可見控件,6個不可見控件。
- 部分控件提供多種樣式風格選擇,多種指示器樣式選擇。
- 所有控件自適應窗體拉伸變化。
- 集成自定義控件屬性設計器,支持拖曳設計,所見即所得,支持導入導出xml格式。
- 自帶activex控件demo,所有控件可以直接運行在ie瀏覽器中。
- 集成fontawesome圖形字體+阿里巴巴iconfont收藏的幾百個圖形字體,享受圖形字體帶來的樂趣。
- 所有控件最后生成一個dll動態庫文件,可以直接集成到qtcreator中拖曳設計使用。
- 目前已經有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、學習方法、寫作技巧、熱門技術、職場發展等內容,干貨多多,福利多多!