测试环境:win10、Qt Creator 4.11.1、5.14.2版本SDK
github:https://github.com/coldfirehello/QtDemo.git
音量需求:
注意事项:
1.音量移动到0或100时,不能有剩余部分。
解决办法:剩余部分设置为背景色!
上代码:
volume.h
#ifndef VOLUME_H
#define VOLUME_H
#include <QWidget>
#include <QSlider>
class Volume : public QWidget
{
Q_OBJECT
public:
explicit Volume(QWidget *parent = nullptr);
~Volume();
void setValue(int value);
signals:
void signalVolumeChanged(int volume);
private:
void initUI();
void onVolumeChanged();
protected:
void paintEvent(QPaintEvent *event) override;
bool event(QEvent *e) override;
private:
QSlider* m_slider;
};
#endif // VOLUME_H
volume.cpp
#include "volume.h"
#include <QApplication>
#include <QEvent>
#include <QPainter>
#include <QStyleOption>
#include <QVBoxLayout>
Volume::Volume(QWidget *parent) : QWidget(parent),
m_slider(nullptr)
{
setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint);
setAttribute(Qt::WA_TranslucentBackground, true);
initUI();
}
Volume::~Volume()
{
}
void Volume::setValue(int value)
{
if(m_slider != nullptr)
{
m_slider->setValue(value);
}
}
void Volume::initUI()
{
QWidget* backgroundWidget = new QWidget(this);
backgroundWidget->resize(36, 153);
backgroundWidget->setStyleSheet("QWidget{background-color:rgba(0, 0, 0, 0.8);border-radius:18px;}");
m_slider = new QSlider();
m_slider->resize(36, 121);
m_slider->setMaximum(100);
m_slider->setMinimum(0);
m_slider->setValue(0);
m_slider->setStyleSheet("QSlider{background:transparent;}"
"QSlider::add-page:vertical{background-color:#FFFFFF;width:4px;border-radius:2px;}"
"QSlider::sub-page:vertical{background-color:rgba(196, 196, 196, 0.5);width:4px;border-radius:2px;}"
"QSlider::groove:vertical{background:transparent;width:4px;border-radius:2px;}"
"QSlider::handle:vertical{height:20px;width:20px;border-image:url(:/images/handle.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:hover{height:20px;width:20px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:pressed{height:20px;width:20px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}");
connect(m_slider, &QSlider::valueChanged, this, &Volume::onVolumeChanged);
QVBoxLayout* vLayout = new QVBoxLayout();
vLayout->setContentsMargins(0, 16, 0, 16);
vLayout->setAlignment(Qt::AlignCenter);
vLayout->setSpacing(0);
vLayout->addWidget(m_slider);
backgroundWidget->setLayout(vLayout);
setValue(10);
}
void Volume::onVolumeChanged()
{
if(m_slider != nullptr)
{
int value = m_slider->value();
if (value == 0)
{
m_slider->setStyleSheet("QSlider{background:transparent;}"
"QSlider::add-page:vertical{background-color:rgba(0, 0, 0, 0.8);width:4px;border-radius:2px;}"
"QSlider::sub-page:vertical{background-color:rgba(196, 196, 196, 0.5);width:4px;border-radius:2px;}"
"QSlider::groove:vertical{background:transparent;width:4px;border-radius:2px;}"
"QSlider::handle:vertical{height:20px;width:21px;border-image:url(:/images/handle.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:hover{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:pressed{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}");
}
else if (value > 0 && value < 100)
{
m_slider->setStyleSheet("QSlider{background:transparent;}"
"QSlider::add-page:vertical{background-color:#FFFFFF;width:4px;border-radius:2px;}"
"QSlider::sub-page:vertical{background-color:rgba(196, 196, 196, 0.5);width:4px;border-radius:2px;}"
"QSlider::groove:vertical{background:transparent;width:4px;border-radius:2px;}"
"QSlider::handle:vertical{height:20px;width:21px;border-image:url(:/images/handle.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:hover{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:pressed{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}");
}
else
{
m_slider->setStyleSheet("QSlider{background:transparent;}"
"QSlider::add-page:vertical{background-color:#FFFFFF;width:4px;border-radius:2px;}"
"QSlider::sub-page:vertical{background-color:rgba(0, 0, 0, 0.8);width:4px;border-radius:2px;}"
"QSlider::groove:vertical{background:transparent;width:4px;border-radius:2px;}"
"QSlider::handle:vertical{height:20px;width:21px;border-image:url(:/images/handle.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:hover{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}"
"QSlider::handle:vertical:pressed{height:20px;width:21px;border-image:url(:/images/plus.png);margin-top:0px;margin-bottom:0px;margin-left:-8px;margin-right:-8px;}");
}
emit signalVolumeChanged(value);
}
}
void Volume::paintEvent(QPaintEvent *event)
{
QStyleOption option;
option.init(this);
QPainter p(this);
style()->drawPrimitive(QStyle::PE_Widget, &option, &p, this);
}
bool Volume::event(QEvent *e)
{
if (e->type() == QEvent::ActivationChange)
{
if (QApplication::activeWindow() != this)
{
this->close();
}
}
return QWidget::event(e);
}
测试代码:
#include "volume.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
Volume w;
w.show();
return a.exec();
}
注意:
因为使用了border-image这种样式,因此groove宽度+扩展宽度最好不小于图片宽度,否则会宽度会缩放。如果使用background-image样式,可能显示位置不对。