2016-10-19 4 views
8

私はかなりよく、スタイルシートを通じてQSliderをカスタマイズする方法を理解し、次のことを行うことが可能である場合、私は疑問に思って:QSliderのハンドルの色をその位置に応じて変更することはできますか?

                                                                                            enter image description here

私は青色から黄色に行くために、スライダーのハンドルをしたいと思います。左に設定すると、青色になります。あなたが右に動かすと、それは青から黄色への勾配を持ちます。

スタイルシートを通してどうすればいいですか?もしそうでなければ、私はそれをQSliderのサブクラスのpaintEventに実装できますか?

+0

QSliderの例(http://doc.qt.io/qt-4.8/stylesheet-examples.html#customizing-qslider)を見ると、qlineargradientを使用すると必要なものが得られるようです。 – Chris

+0

@Chris 1.古い文書へのリンクを張らないでください。 2.これは、ハンドルの内側にグラジエント**を与え、モーションに続くグラディエントではありません。 – IAmInPLS

+1

私は自分の仕事でQt 4を使用していることを残念に思うので、それは私が見慣れたドキュメントです。それがうまくいかない場合は、ペイントイベントでスライダの値を調べ、その値を使ってrgbカラー値を計算します(最初のカラーから最初のカラーまでの直線関係は大丈夫です)。スタイルシートを使用して、ハンドルの色を色に設定できます。最後に、通常のQSliderペイントイベントを呼び出します。 – Chris

答えて

10

あなたがそれを接続することができますので、実際にあなたが本当に、株式QSliderはすでにvalueChanged(int)信号を持っている、空想何もする必要はありません。 2つの色を位置に基づいてミックスし、スタイルの色を設定します。ここで、最小の例である:これは、任意のスライダ範囲及び配向のために働く

static QColor operator+(const QColor & a, const QColor & b) { 
    return QColor(a.red() + b.red(), a.green() + b.green(), a.blue() + b.blue()); 
} 
static QColor operator*(const QColor & c, const qreal r) { 
    return QColor(c.red() * r, c.green() * r, c.blue() * r); 
} 

class Widget : public QWidget { 
    Q_OBJECT 
    public: 
    Widget(QWidget *parent = 0) : QWidget(parent), from(248, 181, 20), to(64, 150, 214) { 
     auto l = new QHBoxLayout(this); 
     setLayout(l); 
     s = new QSlider(Qt::Horizontal, this); 
     s->setMinimum(0); 
     s->setMaximum(100); 
     l->addWidget(s); 
     connect(s, &QSlider::valueChanged, this, &Widget::colorize); 
     colorize(s->value()); 
    } 
    private: 
    void colorize(int v) { 
     int d = s->maximum() - s->minimum(); 
     v = v - s->minimum(); 
     qreal rv = qreal(v)/d; 
     QColor c = from * rv + to * (1.0 - rv); 
     s->setStyleSheet(QString("QSlider::handle:horizontal {background-color: %1;}").arg(c.name())); 
    } 
    QSlider * s; 
    QColor from, to; 
}; 

、コードは、基本的には1.0と0.0の相対ハンドル位置を検出し、ハンドルを設定するfromto色を混合することを利用し色をそれぞれの値に変更します。奇妙なことに、QColorには、乗算と加算を行う演算子がないため、かなり便利です。

enter image description here

また、代わりに2つの色の間の混合のあなたは、あなたのわずかに異なる勾配を与えるHSL形式で色を構築することができます。次いで、それぞれ42および202を色相するQColorからfrom/toをあなたができ変更する:

QColor c = QColor::fromHsl(205 - (205 - 42) * rv, 200, 135); 

これはあなたの温度との関連でより適用することができる2つの固定された色の間の色相ではなくミックスするためのカラースイープを与えます:今、途中であなたは緑の「ゾンビ」のではなく、シアンっぽい色を取得し、あなたがオレンジ色に到達する前に、あなたがきれいな緑を介して取得

enter image description here

注意。

+0

すばらしい答え!私はサブクラスを使わなければならないのを恐れていましたが、素敵なスライダが必要なすべてを私に提供しました! – IAmInPLS

+0

@IAmInPLS - ありがとう、カスタムルックアンドフィールGUI要素が必要な場合は、QMLへの移行を検討する必要があります。 QtWidgetスタックを使用するのと比較してゼロから行うことはほとんどありません。 – dtech

+0

さて、私はプログラムロジックからGUIを分離したくないです。私の考えでは、Qtウィジェットは十分に文書化されているだけでなく、UIも失敗してしまうので、後でQMLを学ぶ機会があります。 – IAmInPLS

4

シンプルなスタイルシートを使用してこれを行うことはできません。しかし、QSliderクラスを特化し、ユーザーがカーソルを移動したときに(つまり、valueChangedがエミットされているときに)適切なスタイルシートを適用すると、簡単に実行できます。

ここではトリックを書いたクラスがあります。それは、水平および垂直カーソルのために動作し、任意の色を使用するようにカスタマイズすることができます。グラデーションカラーマップを格納するためにQLinearGradientからQImageを作成し、スライダの値が変化すると、スライダの位置に基づいて画像から適切な色を抽出し、スタイルシートに適用します。

再利用性のためにクラスを汎用化しようとしましたが、色をカスタマイズする必要がなく、水平スライダのみを使用する必要がない場合は、クラスを簡略化できます。

gradientslider.h:

#include <QSlider> 
#include <QImage> 
#include <QColor> 

class GradientSlider : public QSlider 
{ 
    Q_OBJECT 
public: 
    GradientSlider(QColor from, QColor to, Qt::Orientation orientation, QWidget* parent); 

private slots: 
    void changeColor(int); 

private: 
    QImage gradient; 
}; 

gradientslider.cpp:

#include "gradientslider.h" 
#include <QLinearGradient> 
#include <QPainter> 

GradientSlider::GradientSlider(QColor from, QColor to, Qt::Orientation orientation, QWidget* parent) : 
    QSlider(orientation, parent), 
    gradient(QSize(100,100), QImage::Format_RGB32) 
{ 
    // create linear gradient 
    QLinearGradient linearGrad(QPointF(0, 0), (orientation==Qt::Horizontal) ? QPointF(100, 0) : QPointF(0, 100)); 
    linearGrad.setColorAt(0, from); 
    linearGrad.setColorAt(1, to); 

    // paint gradient in a QImage: 
    QPainter p(&gradient); 
    p.fillRect(gradient.rect(), linearGrad); 

    connect(this, SIGNAL(valueChanged(int)), this, SLOT(changeColor(int))); 

    // initialize 
    changeColor(value()); 
} 

void GradientSlider::changeColor(int pos) 
{ 
    QColor color; 

    if (orientation() == Qt::Horizontal) 
    { 
     // retrieve color index based on cursor position 
     int posIndex = gradient.size().width() * (pos - minimum())/(maximum() - minimum()); 
     posIndex = std::min(posIndex, gradient.width() - 1); 

     // pickup appropriate color 
     color = gradient.pixel(posIndex, gradient.size().height()/2); 
    } 
    else 
    { 
     // retrieve color index based on cursor position 
     int posIndex = gradient.size().height() * (pos - minimum())/(maximum() - minimum()); 
     posIndex = std::min(posIndex, gradient.height() - 1); 

     // pickup appropriate color 
     color = gradient.pixel(gradient.size().width()/2, posIndex); 
    } 

    // create and apply stylesheet! 
    // can be customized to change background and handle border! 
    setStyleSheet("QSlider::handle:" + ((orientation() == Qt::Horizontal) ? QString("horizontal"):QString("vertical")) + "{ \ 
           border-radius: 5px; \ 
           border: 2px solid #FFFFFF; \ 
           width: 20px; \ 
           margin: -5px 0; \ 
           background: " + color.name() + "}"); 
} 

は今だけの操作を行います。

QHBoxLayout* layout = new QHBoxLayout(this); 
// horizontal slider: 
layout->addWidget(new GradientSlider(QColor(79,174,231), QColor(251,192,22), Qt::Horizontal, this)); 
// or, vertical slider: 
layout->addWidget(new GradientSlider(QColor(79,174,231), QColor(251,192,22), Qt::Vertical, this)); 

QColor(79,174,231)(〜青)とQColor(251,192,22)(〜黄色)は元の質問郵便の画像から取り上げられ、Qt::blue,Qt::yellow(わずかに異なる色で終わる)に置き換えることができます。

これはそれを行います。

enter image description here enter image description here enter image description here

+0

サブクラスのための本当に良い答えですので、あなたは私のupvoteを持っています!しかし、私はちょうどスロットのスタイルシートを変更する必要がある答えを受け入れることを理解するでしょう:-)。 – IAmInPLS

+0

@IAmInPLS:私がサブクラスに入れたスロットは、どのクラスでもかまいません。 – jpo38

関連する問題