相比於上一個顏色按鈕面板,此控件就要難不少,顏色值有三種表示形式,除了程序員最經常使用的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等,真的是很是強大,能夠不用管具體的換算細節。linux
#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); } }