2016-10-19 9 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) 신호를 가지고 함수는 위치에 따라 두 색상을 혼합하고 스타일 색상을 설정합니다. 여기서 최소한 예이다

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

또한, 대신에 두 가지 색상을 혼합 당신은 당신에게 약간 다른 기울기를 줄 것이다 HSL 형식의 색상을 구성 할 수 있습니다. 다음, 각각 42, 202 색상을 QColor에서 from/to을 수행 할 수 있습니다 변경 :

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

이렇게하면 온도의 맥락에서 더 적용 할 수있는 두 고정 색상의 색조보다는 믹스 컬러 스윕을 줄 것이다 지금 중간에 당신이 녹색 "좀비"보다는 시안 틱 색상을 얻을 당신이 오렌지에 도착하기 전에 깨끗한 녹색을 통과

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) (~ 파란색)과 012,359,(~ 노란색)은 원래 질문 게시판의 이미지에서 가져 왔으며 Qt::blue, Qt::yellow (약간 다른 채색으로 끝남)으로 바꿀 수 있습니다.

이 그것을 할 것입니다 :

enter image description here 사실 enter image description here enter image description here

+0

정말 서브 클래스에 대한 좋은 답변, 그래서 당신은 내 upvote 있습니다! 그러나, 슬롯에서 스타일 시트를 변경해야하는 경우에는 대답을 받아 들일 것입니다 .-). – IAmInPLS

+0

@IAmInPLS : 하위 클래스에 넣은 슬롯은 어떤 클래스 에나있을 수 있습니다. – jpo38