Qt仿iOS风格的滑动条

由于Qt自带的QSlider自身的限制,无法获得像iOS中的那种滑动条的效果,于是自己做了一个出来
实现原理很简单,使用原有控件组合的方式就可以了

第一步, 继承QWidget 创建一个RichSlider

第二步, 在RichSlider 上先后放置两个QLabel, 然后清空文字内容,设置objName为bgLabel(滑动条背景)、frontLabel (滑动条前景),接着拖动一个QPushButton上去, 清空文本

第三步, 按下面图片中给三个子控件进行布局

这里写图片描述

第四步, 给RichSlider设置样式表来设置各个子控件的背景色和圆角半径

QLabel#bgLabel {
    border-radius: 4px;
    background-color: gray;
}
QLabel#frontLabel {
    border-radius: 4px;
    background-color: green;
}
QPushButton#trackButton {
    border-radius: 8px;
    background-color: white;
}

第五步, 完善头文件中的接口, 包括属性和方法(如setValue(double)等,还有重要的信号valueChanged(double), 本控件中value的值限制在了(0.0 ~ 1.0)直接, 超出范围的值自动忽略

#ifndef RICHSLIDER_H
#define RICHSLIDER_H

#include 
#include 

namespace Ui {
class RichSlider;
}

class RichSlider : public QWidget
{
    Q_OBJECT
    Q_PROPERTY(double value READ value WRITE setValue NOTIFY valueChanged)
    Q_PROPERTY(int tintHeight READ tintHeight WRITE setTintHeight)
    Q_PROPERTY(QColor frontTintColor READ frontTintColor WRITE setFrontTintColor)
    Q_PROPERTY(QColor backgroundTintColor READ backgroundTintColor WRITE setBackgroundTintColor)
    Q_PROPERTY(QColor trackTintColor READ trackTintColor WRITE setTrackTintColor)

public:
    explicit RichSlider(QWidget *parent = 0);
    ~RichSlider();

    double value() const;
    void setValue(double value);

    QColor backgroundTintColor() const;
    void setBackgroundTintColor(const QColor &color);

    QColor frontTintColor() const;
    void setFrontTintColor(const QColor& color);

    QColor trackTintColor() const;
    void setTrackTintColor(const QColor& color);

    QString trackButtonImage() const;
    void setTrackButtonImage(const QString& path);

    int tintHeight() const;
    void setTintHeight(int height);


protected:
    void resizeEvent(QResizeEvent *event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseMoveEvent(QMouseEvent *event) override;
    virtual void layoutChildren();
private:
    void updateStyle();
signals:
    void valueChanged(double);
    void sizeChanged(const QSize&, const QSize&);
private slots:
    void onValueChanged(double);
    void onSizeChanged(const QSize&, const QSize&);
private:
    Ui::RichSlider *ui;
    int _tint_height;
    double _value;
    QColor _track_tint_color;
    QColor _bg_tint_color;
    QColor _fg_tint_color;
    QString _track_button_image;
};

#endif // RICHSLIDER_H

第六步, 实现头文件中所有的方法,并在构造函数中正确初始化成员变量值

#include "richslider.h"
#include "ui_richslider.h"
#include "colorhelper.h"
#include 
#include 

#include 

RichSlider::RichSlider(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::RichSlider)
  , _tint_height(8)
  , _value(0.0)
  , _track_tint_color(Qt::white)
  , _bg_tint_color(Qt::gray)
  , _fg_tint_color(Qt::green)
{
    ui->setupUi(this);
    connect(this, SIGNAL(sizeChanged(QSize,QSize)), SLOT(onSizeChanged(QSize,QSize)));
    connect(this, SIGNAL(valueChanged(double)), SLOT(onValueChanged(double)));
}

RichSlider::~RichSlider()
{
    delete ui;
}

double RichSlider::value() const
{
    return _value;
}

void RichSlider::setValue(double value)
{
    if(0.0 <= value && value <= 1.0 && _value != value) {
        _value = value;
        emit valueChanged(_value);
    }
}

QColor RichSlider::backgroundTintColor() const
{
    return _bg_tint_color;
}

void RichSlider::setBackgroundTintColor(const QColor &color)
{
    _bg_tint_color = color;
    updateStyle();
}

QColor RichSlider::frontTintColor() const
{
    return _fg_tint_color;
}

void RichSlider::setFrontTintColor(const QColor &color)
{
    _fg_tint_color = color;
    updateStyle();
}

QColor RichSlider::trackTintColor() const
{
    return _track_tint_color;
}

void RichSlider::setTrackTintColor(const QColor &color)
{
    _track_tint_color = color;
    updateStyle();
}
void RichSlider::setTintHeight(int height)
{
    if(_tint_height != height && _tint_height < geometry().height()) {
        _tint_height = height;
        layoutChildren();
    }
}


QString RichSlider::trackButtonImage() const
{
    return _track_button_image;
}

void RichSlider::setTrackButtonImage(const QString &path)
{
    _track_button_image = path;
    updateStyle();
}

void RichSlider::layoutChildren()
{
    auto w = width();
    auto h = height();

    auto tintY = (h - _tint_height) / 2;
    auto trackTintX = (w - h) * _value;

    ui->bgLabel->setGeometry(h / 2, tintY, w - h, _tint_height);
    ui->frontLabel->setGeometry(h / 2, tintY, (w - h) * _value, _tint_height);
    ui->trackButton->setGeometry(trackTintX, 0, h, h);
    updateStyle();
}

void RichSlider::resizeEvent(QResizeEvent *event)
{
    emit sizeChanged(event->oldSize(), event->size());
}

void RichSlider::mousePressEvent(QMouseEvent *ev)
{
    auto x = ev->pos().x(); // mouse pos  in RichSlider
    auto value = static_cast<double>(x) / width();
    setValue(value);
}

void RichSlider::mouseMoveEvent(QMouseEvent *ev)
{
    auto x = ev->pos().x(); // mouse pos  in RichSlider
    auto y = ev->pos().y();
    if(0 <= y && y <= height()) {
        auto value = static_cast<double>(x - height() / 2) / (width() - height());
        setValue(value);
    }
}



int RichSlider::tintHeight() const
{
    return _tint_height;
}



void RichSlider::onSizeChanged(const QSize &, const QSize &)
{
    layoutChildren();
    updateStyle();
}

void RichSlider::onValueChanged(double)
{
    layoutChildren();
}

void RichSlider::updateStyle()
{
    QString qss(R"(
                QLabel#bgLabel {
                    border-radius: %1px;
                    background-color: %2;
                }
                QLabel#frontLabel {
                    border-radius: %3px;
                    background-color: %4;
                }
                QPushButton#trackButton {
                    border-radius: %5px;
                    background-color: %6;
                }
    )");

    setStyleSheet(qss
                  .arg(ui->bgLabel->height() / 2) // bgLabel border-radius
                  .arg(ColorHelper::makeColorString(_bg_tint_color)) // bgLabel background-color
                  .arg(ui->frontLabel->height() / 2) // frontLabel border-radius
                  .arg(ColorHelper::makeColorString(_fg_tint_color)) // frontLabel background-color
                  .arg(ui->trackButton->height() / 2) // track button border-radius
                  .arg(ColorHelper::makeColorString(_track_tint_color))); // track button background-color


    update();
}

以下是实验效果图:

Qt仿iOS风格的滑动条_第1张图片

温馨提示: 上面代码中用到了一个颜色工具, 读者可以自己实现一个ColorHelper工具类,并实现一个
QString makeColorString(const QColor& color, const QString& type)的静态方法即可。实现可以参考我的另一篇博文QColor转QString

你可能感兴趣的:(C++,Qt,C++,Qt,滑动条,Slider)