fix: 调整快捷设置声音、亮度滚动条样式

1、滚动条样式和设计图保持一致
2、滚动条右侧的图标增加阴影

Log:
Influence: 滚动条-快捷设置面板
Task: https://pms.uniontech.com/task-view-110309.html
Change-Id: I3b4680c94efeb433d22cd3a1ab5d5745d456c3aa
This commit is contained in:
donghualin 2022-05-27 09:27:33 +08:00
parent e9db102f26
commit 7c3db6c9be
9 changed files with 155 additions and 99 deletions

View File

@ -20,6 +20,7 @@
*/
#include "quicksettingitem.h"
#include "pluginsiteminterface.h"
#include "imageutil.h"
#include <DGuiApplicationHelper>
#include <DFontSizeManager>
@ -113,15 +114,8 @@ void QuickSettingItem::paintEvent(QPaintEvent *e)
int marginXSpace = xMarginSpace();
int marginYSpace = yMarginSpace();
QRect iconBg(marginXSpace, marginYSpace, BGSIZE, BGSIZE);
painter.save();
painter.setPen(Qt::NoPen);
painter.setBrush(shadowColor());
painter.drawEllipse(iconBg);
painter.restore();
QRect rctIcon(iconBg.x() + (iconBg.width() - ICONWIDTH) / 2,
iconBg.y() + (iconBg.height() - ICONHEIGHT) / 2,
ICONWIDTH, ICONHEIGHT);
painter.drawPixmap(rctIcon, pm);
QPixmap bgPixmap = ImageUtil::getShadowPixmap(pm, shadowColor(), QSize(BGSIZE, BGSIZE));
painter.drawPixmap(iconBg, bgPixmap);
// 绘制文字
painter.setPen(QColor(0, 0, 0));
@ -148,10 +142,10 @@ void QuickSettingItem::paintEvent(QPaintEvent *e)
painter.setPen(pen);
int iconLeft = rect().width() - marginXSpace - expandSize.width();
int iconRight = rect().width() - marginXSpace;
painter.drawLine(QPoint(iconLeft, (rctIcon.y() + (rctIcon.height() - expandSize.height()) / 2)),
QPoint(iconRight, (rctIcon.y() + rctIcon.height() / 2)));
painter.drawLine(QPoint(iconRight, (rctIcon.y() + rctIcon.height() / 2)),
QPoint(iconLeft, (rctIcon.y() + (rctIcon.height() + expandSize.height()) / 2)));
painter.drawLine(QPoint(iconLeft, (iconBg.y() + (iconBg.height() - expandSize.height()) / 2)),
QPoint(iconRight, (iconBg.y() + iconBg.height() / 2)));
painter.drawLine(QPoint(iconRight, (iconBg.y() + iconBg.height() / 2)),
QPoint(iconLeft, (iconBg.y() + (iconBg.height() + expandSize.height()) / 2)));
} else {
// 绘制图标
QRect rctIcon = iconRect();

View File

@ -26,6 +26,9 @@
#include <QCursor>
#include <QGSettings>
#include <QDebug>
#include <QPainterPath>
#include <QRegion>
#include <QBitmap>
#include <X11/Xcursor/Xcursor.h>
@ -81,3 +84,36 @@ QCursor* ImageUtil::loadQCursorFromX11Cursor(const char* theme, const char* curs
XcursorImagesDestroy(images);
return cursor;
}
const QPixmap ImageUtil::getShadowPixmap(const QPixmap &pixmap, const QColor &shadowColor, const QSize &backSize)
{
// 新建一个bitmap作为遮罩尺寸为外部指定(backSize)
QBitmap bitmap(backSize);
QPainter painter(&bitmap);
painter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
painter.setPen(Qt::NoPen);
// 往bitmap上绘制圆形区域
QRect rectBackground(0, 0, backSize.width(), backSize.height());
painter.fillRect(rectBackground, Qt::white);
painter.setBrush(Qt::black);
painter.drawEllipse(0, 0, backSize.width(), backSize.height());
// 新建QPixmap将上述新建的Bitmap作为它的遮罩
QPixmap newPixmap(backSize);
newPixmap.setMask(bitmap);
QPainter pixPainter(&newPixmap);
pixPainter.setRenderHints(QPainter::Antialiasing | QPainter::SmoothPixmapTransform);
const QSize iconSize = pixmap.size();
int startX = (backSize.width() - iconSize.width()) / 2;
int startY = (backSize.height() - iconSize.height()) / 2;
// 将传入参数的背景尺寸(backSize)作为背景,通过画笔路径在上面绘制圆形区域
QRect rectPixmap(startX, startY, iconSize.width(), iconSize.height());
QPainterPath path;
path.addEllipse(rectBackground);
pixPainter.fillPath(path, shadowColor);
// 将图像绘制到新建的QPixmap的背景区域并返回新的QPixmap
pixPainter.drawPixmap(rectPixmap, pixmap);
pixPainter.setPen(shadowColor);
pixPainter.drawEllipse(rectBackground);
return newPixmap;
}

View File

@ -35,6 +35,7 @@ public:
static const QPixmap loadSvg(const QString &iconName, const QString &localPath, const int size, const qreal ratio);
static const QPixmap loadSvg(const QString &iconName, const QSize size, const qreal ratio = qApp->devicePixelRatio());
static QCursor* loadQCursorFromX11Cursor(const char* theme, const char* cursorName, int cursorSize);
static const QPixmap getShadowPixmap(const QPixmap &pixmap, const QColor &shadowColor, const QSize &backSize);
};
#endif // IMAGEUTIL_H

View File

@ -22,10 +22,14 @@
#include "customslider.h"
#include "brightnessmodel.h"
#include "brightnessmonitorwidget.h"
#include "imageutil.h"
#include <QHBoxLayout>
#include <QDebug>
#define BACKSIZE 36
#define IMAGESIZE 24
BrightnessWidget::BrightnessWidget(QWidget *parent)
: DBlurEffectWidget(parent)
, m_slider(new CustomSlider(CustomSlider::SliderType::Normal, this))
@ -63,11 +67,16 @@ void BrightnessWidget::initUi()
layout->addWidget(m_slider);
m_slider->setPageStep(1);
m_slider->setIconSize(QSize(24, 24));
m_slider->setIconSize(QSize(BACKSIZE, BACKSIZE));
m_slider->setLeftIcon(QIcon(":/icons/resources/brightness.svg"));
m_slider->setRightIcon(QIcon::fromTheme(":/icons/resources/ICON_Device_Laptop.svg"));
m_slider->setTickPosition(QSlider::TicksBelow);
QIcon leftIcon(QPixmap(":/icons/resources/brightness.svg").scaled(IMAGESIZE, IMAGESIZE));
m_slider->setLeftIcon(leftIcon);
QPixmap rightPixmap = ImageUtil::getShadowPixmap(QPixmap(QString(":/icons/resources/ICON_Device_Laptop.svg")).scaled(24, 24), Qt::lightGray, QSize(36, 36));
m_slider->setRightIcon(rightPixmap);
SliderProxy *style = new SliderProxy;
style->setParent(m_slider->qtSlider());
m_slider->qtSlider()->setStyle(style);
}
void BrightnessWidget::initConenction()

View File

@ -20,9 +20,11 @@
*/
#include "customslider.h"
#include <QPainterPath>
#include <DStyle>
#include <DApplicationHelper>
#include <DGuiApplicationHelper>
#include <QMouseEvent>
#include <QDebug>
@ -34,7 +36,6 @@ DWIDGET_USE_NAMESPACE
CustomSlider::CustomSlider(CustomSlider::SliderType type, QWidget *parent)
: DSlider(Qt::Horizontal, parent)
, m_separateValue(0)
{
setType(type);
DSlider::slider()->setTracking(false);
@ -100,79 +101,11 @@ void CustomSlider::setOrientation(Qt::Orientation orientation)
Q_UNUSED(orientation)
}
void CustomSlider::setSeparateValue(int value)
{
m_separateValue = value;
}
void CustomSlider::wheelEvent(QWheelEvent *e)
{
e->ignore();
}
void CustomSlider::paintEvent(QPaintEvent *e)
{
Q_UNUSED(e)
if (m_separateValue <= 0)
return;
QPainter pa(this);
auto dpa = DApplicationHelper::instance()->palette(this);
QPen penLine = QPen(dpa.color(DPalette::ObviousBackground), 2);
//超过间隔线后需要更换间隔线颜色为活动色
if (qtSlider()->value() >= m_separateValue ) {
QPalette pe = this->palette();
QColor brushColor(pe.color(QPalette::Highlight));
penLine.setColor(brushColor);
}
int margin = DStyle::pixelMetric(style(), DStyle::PM_FocusBorderSpacing) + DStyle::pixelMetric(style(), DStyle::PM_FocusBorderSpacing);
int offsetSize = style()->pixelMetric(QStyle::PM_SliderLength, nullptr, this) / 2;
int width = this->qtSlider()->width();
width -= 2 * offsetSize + margin * 2;
Qt::Orientation orient = this->orientation();
QSlider::TickPosition tick = m_tickPosition;
QSlider* slider = DSlider::slider();
qreal percentage = (m_separateValue - slider->minimum()) * 1.0 / (slider->maximum() - slider->minimum());
pa.setPen(penLine);
int leftIconwidth = 0;
//获取左边声音图标宽度
QGridLayout *gridLayout = dynamic_cast<QGridLayout *>(this->layout());
if (!gridLayout)
return;
QLayoutItem* item = gridLayout->itemAtPosition(1, 0);
if (item) {
leftIconwidth = item->geometry().size().width();
}
qreal startX = offsetSize + margin + leftIconwidth + this->contentsMargins().left();
qreal startY = slider->y() + 10;
//分别绘制滑动条上方矩形和下方矩形,避免与滑动条重叠,
//画笔宽为2个像素,设置绘制时矩形高设为3,可达到高度为5的效果
if (orient == Qt::Horizontal) {
qreal sliderX = percentage * width;
if (slider->value() >= m_separateValue) {
int num = (sliderX + 2) / 3;
qAbs(3 * num + 1 - sliderX) - qAbs(sliderX - (3 * num - 2)) >= 0 ? num : num++;
sliderX = 3 * num - 2;
} else {
//将分割线左、右的滚动条进行比较获取距离最相近的位置,绘制分割线
sliderX = (slider->maximum() - m_separateValue) * 1.0 * width / slider->maximum();
int num = (sliderX + 1) / 3;
qAbs(3 * num - sliderX) - qAbs(sliderX - 3 * (num - 1)) >= 0 ? num : num++;
sliderX = width - (3 * num - 1);
}
if (tick == QSlider::TicksAbove || tick == QSlider::TicksBelow || tick == QSlider::NoTicks) {
pa.drawLine(QPointF(startX + sliderX, startY), QPointF(startX + sliderX, startY + 3));
pa.drawLine(QPointF(startX + sliderX, startY + 9), QPointF(startX + sliderX, startY + 12));
}
}
}
SliderContainer::SliderContainer(CustomSlider::SliderType type, QWidget *parent)
: QWidget (parent)
, m_slider(new CustomSlider(type, this))
@ -212,3 +145,48 @@ CustomSlider *SliderContainer::slider()
{
return m_slider;
}
SliderProxy::SliderProxy(QStyle *style)
: QProxyStyle(style)
{
}
SliderProxy::~SliderProxy()
{
}
void SliderProxy::drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget) const
{
if (control != ComplexControl::CC_Slider)
return;
// 绘制之前先保存之前的画笔
painter->save();
painter->setRenderHint(QPainter::RenderHint::Antialiasing);
// 获取滑动条和滑块的区域
const QStyleOptionSlider *sliderOption = static_cast<const QStyleOptionSlider *>(option);
QRect rectGroove = subControlRect(CC_Slider, sliderOption, SC_SliderGroove, widget);
QRect rectHandle = subControlRect(CC_Slider, sliderOption, SC_SliderHandle, widget);
// 深色背景下,滑块和滑动条白色,浅色背景下,滑块和滑动条黑色
QBrush brush(DGuiApplicationHelper::DarkType == DGuiApplicationHelper::instance()->themeType() ? Qt::white : Qt::black);
// 此处中绘制圆形滑动条,需要绘制圆角,圆角大小为其高度的一半
QPainterPath pathGroove;
int radius = rectGroove.height() / 2;
pathGroove.addRoundedRect(rectGroove, radius, radius);
painter->fillPath(pathGroove, brush);
// 绘制滑块,因为滑块是正圆形,而它本来的区域是一个长方形区域,因此,需要计算当前
// 区域的正中心区域,将其作为一个正方形区域来绘制圆形滑块
int handleSize = qMin(rectHandle.width(), rectHandle.height());
int x = rectHandle.x() + (rectHandle.width() - handleSize) / 2;
int y = rectHandle.y() + (rectHandle.height() - handleSize) / 2;
rectHandle.setX(x);
rectHandle.setY(y);
rectHandle.setWidth(handleSize);
rectHandle.setHeight(handleSize);
QPainterPath pathHandle;
pathHandle.addEllipse(rectHandle);
painter->fillPath(pathHandle, brush);
painter->restore();
}

View File

@ -23,6 +23,7 @@
#define CUSTOMCTRL_H
#include <DSlider>
#include <QProxyStyle>
#include <QTimer>
class QLabel;
@ -52,15 +53,12 @@ public:
void setSliderPosition(int Position);
void setAnnotations(const QStringList &annotations);
void setOrientation(Qt::Orientation orientation);
//当value大于0时在slider中插入一条分隔线
void setSeparateValue(int value = 0);
protected:
void wheelEvent(QWheelEvent *e);
void paintEvent(QPaintEvent *e);
private:
QSlider::TickPosition m_tickPosition = QSlider::TicksBelow;
int m_separateValue;
};
class SliderContainer : public QWidget
@ -79,4 +77,16 @@ private:
QLabel *m_titleLabel;
};
class SliderProxy : public QProxyStyle
{
Q_OBJECT
public:
explicit SliderProxy(QStyle *style = nullptr);
~SliderProxy() override;
protected:
void drawComplexControl(QStyle::ComplexControl control, const QStyleOptionComplex *option, QPainter *painter, const QWidget *widget = nullptr) const override;
};
#endif // VOLUMESLIDER_H

View File

@ -18,6 +18,7 @@
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "customslider.h"
#include "mediawidget.h"
#include <DFontSizeManager>
@ -151,6 +152,7 @@ void MediaWidget::onUpdateMediaInfo()
* @brief
* @param parent
*/
MusicButton::MusicButton(QWidget *parent)
: QWidget(parent)
{
@ -161,14 +163,28 @@ MusicButton::~MusicButton()
{
}
int MusicButton::getIconHeight() const
{
switch (m_buttonType) {
case ButtonType::Pause:
return 21;
case ButtonType::Next:
case ButtonType::Playing:
return 18;
}
return 18;
}
void MusicButton::paintEvent(QPaintEvent *event)
{
#define ICONHEIGHT 20
Q_UNUSED(event);
int ctrlHeight = getIconHeight();
int width = this->width();
int height = this->height();
int startX = 2;
int startY = (height - ICONHEIGHT) / 2;
int startY = (height - ctrlHeight) / 2;
QColor color(0, 0, 0);
QPainter painter(this);
painter.save();
@ -176,17 +192,17 @@ void MusicButton::paintEvent(QPaintEvent *event)
painter.setPen(color);
painter.setBrush(color);
if (m_buttonType == ButtonType::Pause) {
painter.drawRect(QRect(startX, startY, 6, ICONHEIGHT));
painter.drawRect(QRect(width - 6 - 2, startY, 6, ICONHEIGHT));
painter.drawRect(QRect(startX, startY, 6, ctrlHeight));
painter.drawRect(QRect(width - 6 - 2, startY, 6, ctrlHeight));
} else {
QPainterPath trianglePath;
trianglePath.moveTo(startX, startY);
trianglePath.lineTo(width - 6, height / 2);
trianglePath.lineTo(startX, startY + ICONHEIGHT);
trianglePath.lineTo(startX, startY + ctrlHeight);
trianglePath.lineTo(startX, startY);
painter.drawPath(trianglePath);
if (m_buttonType == ButtonType::Next)
painter.drawRect(width - 6, startY, 2, ICONHEIGHT);
painter.drawRect(width - 6, startY, 2, ctrlHeight);
}
painter.restore();
}

View File

@ -87,6 +87,9 @@ protected:
void paintEvent(QPaintEvent *event) override;
void mouseReleaseEvent(QMouseEvent *event) override;
private:
int getIconHeight() const;
private:
ButtonType m_buttonType;
};

View File

@ -22,6 +22,7 @@
#include "customslider.h"
#include "imageutil.h"
#include "volumemodel.h"
#include "imageutil.h"
#include <DGuiApplicationHelper>
@ -41,6 +42,7 @@
DGUI_USE_NAMESPACE
#define ICON_SIZE 24
#define BACKSIZE 36
VolumeWidget::VolumeWidget(QWidget *parent)
: DBlurEffectWidget(parent)
@ -65,9 +67,16 @@ void VolumeWidget::initUi()
mainLayout->setContentsMargins(20, 0, 20, 0);
mainLayout->addWidget(m_volumnCtrl);
m_volumnCtrl->setIconSize(QSize(36, 36));
m_volumnCtrl->setLeftIcon(QIcon(leftIcon()));
m_volumnCtrl->setRightIcon(QIcon(rightIcon()));
const QString rightIconFile = rightIcon();
QIcon rIcon = ImageUtil::getShadowPixmap(QPixmap(rightIconFile), Qt::lightGray, QSize(BACKSIZE, BACKSIZE));
m_volumnCtrl->setIconSize(QSize(BACKSIZE, BACKSIZE));
m_volumnCtrl->setLeftIcon(QIcon(QPixmap(leftIcon())));
m_volumnCtrl->setRightIcon(rIcon);
SliderProxy *proxy = new SliderProxy;
proxy->setParent(m_volumnCtrl->qtSlider());
m_volumnCtrl->qtSlider()->setStyle(proxy);
bool existActiveOutputDevice = m_volumeController->existActiveOutputDevice();
setEnabled(existActiveOutputDevice);