mirror of
https://github.com/Linloir/SceneEditor.git
synced 2025-12-16 23:18:12 +08:00
[UI][ADD] Slider widget
- Non-linear value transformation - Color scheme selection - Redesigned signals
This commit is contained in:
parent
0f6a58a645
commit
c89e445668
288
FinalProject/slider.cpp
Normal file
288
FinalProject/slider.cpp
Normal file
@ -0,0 +1,288 @@
|
||||
#include <qregularexpression.h>
|
||||
|
||||
#include "slider.h"
|
||||
|
||||
Slider::Slider(float min, float max, int step, QWidget* parent) :
|
||||
QWidget(parent), _min(min), _max(max), _step(step)
|
||||
{
|
||||
// Set map functions
|
||||
_transformFunc = [this](float x) {
|
||||
// Map x of [0, step] to [_min, _max]
|
||||
float y = x / _step * (_max - _min) + _min;
|
||||
return y;
|
||||
};
|
||||
_inversionFunc = [this](float y) {
|
||||
// Map y of [_min, _max] to [0, step]
|
||||
float x = (y - _min) / (_max - _min) * _step;
|
||||
return x;
|
||||
};
|
||||
// Generate colors
|
||||
generateColor(_defaultSchemeColor);
|
||||
// Create main layout
|
||||
_mainLayout = new QHBoxLayout(this);
|
||||
_mainLayout->setContentsMargins(4, 4, 4, 4);
|
||||
_mainLayout->setSpacing(0);
|
||||
setLayout(_mainLayout);
|
||||
// Create slider
|
||||
_slider = new QSlider(Qt::Horizontal, this);
|
||||
_slider->setMinimum(0);
|
||||
_slider->setMaximum(_step);
|
||||
_slider->setSingleStep(1);
|
||||
// Set slider style sheet
|
||||
QString grooveStyle = "QSlider::groove:horizontal {"
|
||||
"height:6px;"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString sliderStyle = "QSlider::handle:horizontal {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _handleColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderHoverStyle = "QSlider::handle:horizontal:hover {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _hoverColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderPressStyle = "QSlider::handle:horizontal:pressed {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _pressColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString subStyle = "QSlider::sub-page:horizontal {"
|
||||
"background:" + _subColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString addStyle = "QSlider::add-page:horizontal {"
|
||||
"background:" + _addColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
_slider->setStyleSheet(grooveStyle + sliderStyle + sliderHoverStyle + sliderPressStyle + subStyle + addStyle);
|
||||
// Create decrease button
|
||||
_decreaseBtn = new PushButton(nullptr, this);
|
||||
_decreaseBtn->setColorScheme(_defaultSchemeColor);
|
||||
_decreaseBtn->setFixedSize(24, 24);
|
||||
_decreaseBtn->setRadius(8);
|
||||
_decreaseBtn->setMargin(0, 0, 0, 3);
|
||||
_decreaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
// Create decrease label
|
||||
_decreaseIcon = new QLabel(_decreaseBtn);
|
||||
_decreaseIcon->setFont(QFont("Font Awesome 6 Free Solid", 6));
|
||||
_decreaseIcon->setText("\uf068");
|
||||
_decreaseIcon->setAlignment(Qt::AlignCenter);
|
||||
_decreaseBtn->setChildWidget(_decreaseIcon);
|
||||
_decreaseIcon->show();
|
||||
// Create increase button
|
||||
_increaseBtn = new PushButton(nullptr, this);
|
||||
_increaseBtn->setColorScheme(_defaultSchemeColor);
|
||||
_increaseBtn->setFixedSize(24, 24);
|
||||
_increaseBtn->setRadius(8);
|
||||
_increaseBtn->setMargin(0, 0, 0, 3);
|
||||
_increaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
// Create increase label
|
||||
_increaseIcon = new QLabel(_increaseBtn);
|
||||
_increaseIcon->setFont(QFont("Font Awesome 6 Free Solid", 6));
|
||||
_increaseIcon->setText("\uf067");
|
||||
_increaseIcon->setAlignment(Qt::AlignCenter);
|
||||
_increaseBtn->setChildWidget(_increaseIcon);
|
||||
_increaseIcon->show();
|
||||
// Add to main layout
|
||||
_mainLayout->addWidget(_decreaseBtn);
|
||||
_mainLayout->addSpacing(4);
|
||||
_mainLayout->addWidget(_slider);
|
||||
_mainLayout->addSpacing(4);
|
||||
_mainLayout->addWidget(_increaseBtn);
|
||||
_decreaseBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
_slider->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Fixed);
|
||||
_increaseBtn->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed);
|
||||
_decreaseBtn->show();
|
||||
_slider->show();
|
||||
_increaseBtn->show();
|
||||
// Connect signals and slots
|
||||
connect(_decreaseBtn, &PushButton::onClick, this, [this]() {
|
||||
// Set current value
|
||||
_slider->setValue(_slider->value() - 1);
|
||||
emit onChanged(_transformFunc(_slider->value()));
|
||||
emit onSetValue(_transformFunc(_slider->value()));
|
||||
emit onDragEnd();
|
||||
});
|
||||
connect(_increaseBtn, &PushButton::onClick, this, [this]() {
|
||||
// Set current value
|
||||
_slider->setValue(_slider->value() + 1);
|
||||
emit onChanged(_transformFunc(_slider->value()));
|
||||
emit onSetValue(_transformFunc(_slider->value()));
|
||||
emit onDragEnd();
|
||||
});
|
||||
connect(_slider, &QSlider::valueChanged, this, [this](int value) {
|
||||
// Judge whether the slider is changed by dragging or function
|
||||
if (_slider->isSliderDown()) {
|
||||
// Value changed by user
|
||||
emit onChanged(_transformFunc(value));
|
||||
}
|
||||
emit onSetValue(_transformFunc(value));
|
||||
});
|
||||
connect(_slider, &QSlider::sliderPressed, this, &Slider::onDragStart);
|
||||
connect(_slider, &QSlider::sliderReleased, this, &Slider::onDragEnd);
|
||||
}
|
||||
|
||||
Slider::~Slider()
|
||||
{}
|
||||
|
||||
void Slider::generateColor(QColor schemeColor) {
|
||||
_subColor = schemeColor;
|
||||
_addColor = QColor(216, 216, 216);
|
||||
_handleColor = QColor(194, 194, 194);
|
||||
_hoverColor = schemeColor.lighter(20);
|
||||
float hoverBlendRatio = 0.2;
|
||||
_hoverColor = QColor(
|
||||
_hoverColor.red() * hoverBlendRatio + _handleColor.red() * (1 - hoverBlendRatio),
|
||||
_hoverColor.green() * hoverBlendRatio + _handleColor.green() * (1 - hoverBlendRatio),
|
||||
_hoverColor.blue() * hoverBlendRatio + _handleColor.blue() * (1 - hoverBlendRatio)
|
||||
);
|
||||
_pressColor = schemeColor.lighter(20);
|
||||
float pressBlendRatio = 0.5;
|
||||
_pressColor = QColor(
|
||||
_pressColor.red() * pressBlendRatio + _handleColor.red() * (1 - pressBlendRatio),
|
||||
_pressColor.green() * pressBlendRatio + _handleColor.green() * (1 - pressBlendRatio),
|
||||
_pressColor.blue() * pressBlendRatio + _handleColor.blue() * (1 - pressBlendRatio)
|
||||
);
|
||||
}
|
||||
|
||||
void Slider::setColorScheme(QColor color) {
|
||||
generateColor(color);
|
||||
// Change style sheet
|
||||
QString grooveStyle = "QSlider::groove:horizontal {"
|
||||
"height:6px;"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString sliderStyle = "QSlider::handle:horizontal {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _handleColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderHoverStyle = "QSlider::handle:horizontal:hover {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _hoverColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderPressStyle = "QSlider::handle:horizontal:pressed {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _pressColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString subStyle = "QSlider::sub-page:horizontal {"
|
||||
"background:" + _subColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString addStyle = "QSlider::add-page:horizontal {"
|
||||
"background:" + _addColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
_slider->setStyleSheet(grooveStyle + sliderStyle + sliderHoverStyle + sliderPressStyle + subStyle + addStyle);
|
||||
// Change button color
|
||||
_decreaseBtn->setColorScheme(color);
|
||||
_decreaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
_increaseBtn->setColorScheme(color);
|
||||
_increaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
}
|
||||
|
||||
void Slider::setMin(float min) {
|
||||
_min = min;
|
||||
}
|
||||
|
||||
void Slider::setMax(float max) {
|
||||
_max = max;
|
||||
}
|
||||
|
||||
void Slider::setStep(float step) {
|
||||
_step = step;
|
||||
_slider->setMaximum(step);
|
||||
}
|
||||
|
||||
void Slider::setValue(float value) {
|
||||
_slider->setValue((int)_inversionFunc(value));
|
||||
}
|
||||
|
||||
void Slider::setTransformation(std::function<float(float)> transformFunc, std::function<float(float)> inversionFunc) {
|
||||
_transformFunc = transformFunc;
|
||||
_inversionFunc = inversionFunc;
|
||||
}
|
||||
|
||||
void Slider::setEnabled(bool enabled) {
|
||||
if (enabled == _enabled) {
|
||||
return;
|
||||
}
|
||||
_enabled = enabled;
|
||||
_slider->setEnabled(enabled);
|
||||
_decreaseBtn->setEnabled(enabled);
|
||||
_increaseBtn->setEnabled(enabled);
|
||||
if (!enabled) {
|
||||
// Store colors
|
||||
_restoredColor[0] = _subColor;
|
||||
_restoredColor[1] = _addColor;
|
||||
_restoredColor[2] = _handleColor;
|
||||
_restoredColor[3] = _hoverColor;
|
||||
_restoredColor[4] = _pressColor;
|
||||
// Change colors
|
||||
setColorScheme(QColor(200, 200, 200));
|
||||
}
|
||||
else {
|
||||
// Restore colors
|
||||
_subColor = _restoredColor[0];
|
||||
_addColor = _restoredColor[1];
|
||||
_handleColor = _restoredColor[2];
|
||||
_hoverColor = _restoredColor[3];
|
||||
_pressColor = _restoredColor[4];
|
||||
// Change style sheet
|
||||
QString grooveStyle = "QSlider::groove:horizontal {"
|
||||
"height:6px;"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString sliderStyle = "QSlider::handle:horizontal {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _handleColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderHoverStyle = "QSlider::handle:horizontal:hover {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _hoverColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString sliderPressStyle = "QSlider::handle:horizontal:pressed {"
|
||||
"width:12px;"
|
||||
"margin-bottom:-3px;"
|
||||
"margin-top:-3px;"
|
||||
"background:" + _pressColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:6px;"
|
||||
"}";
|
||||
QString subStyle = "QSlider::sub-page:horizontal {"
|
||||
"background:" + _subColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
QString addStyle = "QSlider::add-page:horizontal {"
|
||||
"background:" + _addColor.name(QColor::HexArgb) + ";"
|
||||
"border-radius:3px;"
|
||||
"}";
|
||||
_slider->setStyleSheet(grooveStyle + sliderStyle + sliderHoverStyle + sliderPressStyle + subStyle + addStyle);
|
||||
// Change button color
|
||||
_decreaseBtn->setColorScheme(_subColor);
|
||||
_decreaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
_increaseBtn->setColorScheme(_subColor);
|
||||
_increaseBtn->setIndicatorColor(QColor(255, 255, 255, 0));
|
||||
}
|
||||
}
|
||||
72
FinalProject/slider.h
Normal file
72
FinalProject/slider.h
Normal file
@ -0,0 +1,72 @@
|
||||
#pragma once
|
||||
|
||||
#include <qwidget.h>
|
||||
#include <qboxlayout.h>
|
||||
#include <qslider.h>
|
||||
#include <qlabel.h>
|
||||
|
||||
#include "pushbutton.h"
|
||||
|
||||
class Slider : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
Slider(float min, float max, int step, QWidget* parent = 0);
|
||||
~Slider();
|
||||
|
||||
private:
|
||||
// Settings
|
||||
float _min;
|
||||
float _max;
|
||||
int _step; // step count of slider value
|
||||
|
||||
// State
|
||||
bool _enabled = true;
|
||||
|
||||
// UI Settings
|
||||
const QColor _defaultSchemeColor = QColor(58, 143, 183);
|
||||
QColor _subColor;
|
||||
QColor _addColor;
|
||||
QColor _handleColor;
|
||||
QColor _hoverColor;
|
||||
QColor _pressColor;
|
||||
QColor _restoredColor[5];
|
||||
|
||||
// UI Layout
|
||||
QHBoxLayout* _mainLayout;
|
||||
QSlider* _slider;
|
||||
PushButton* _decreaseBtn;
|
||||
QLabel* _decreaseIcon;
|
||||
PushButton* _increaseBtn;
|
||||
QLabel* _increaseIcon;
|
||||
|
||||
// Transformation function
|
||||
std::function<float(float)> _transformFunc; // Transform the slider value to actual value
|
||||
std::function<float(float)> _inversionFunc; // Transform the actual value to slider value
|
||||
|
||||
private:
|
||||
void generateColor(QColor schemeColor);
|
||||
|
||||
public:
|
||||
// Getter APIs
|
||||
QHBoxLayout* mainLayout() const { return _mainLayout; }
|
||||
float val() const { return _transformFunc(_slider->value()); }
|
||||
float lev() const { return _slider->value(); }
|
||||
|
||||
// Setter APIs
|
||||
void setColorScheme(QColor color);
|
||||
void setMin(float min);
|
||||
void setMax(float max);
|
||||
void setStep(float max);
|
||||
void setValue(float val); // Set the actual value
|
||||
void setTransformation(std::function<float(float)> transform, std::function<float(float)> inverse);
|
||||
|
||||
void setEnabled(bool enabled = true);
|
||||
|
||||
signals:
|
||||
void onChanged(float newVal); // Triggers only when user changes the value
|
||||
void onSetValue(float newVal); // Triggers when user changes the value or setValue() is called
|
||||
void onDragStart();
|
||||
void onDragEnd();
|
||||
};
|
||||
Loading…
x
Reference in New Issue
Block a user