Refactor SlidePickerBox.

This commit is contained in:
Krad
2022-06-07 15:10:42 +08:00
parent 5f8e33d2e3
commit 365386d50b
2 changed files with 140 additions and 183 deletions

View File

@@ -3,125 +3,113 @@
//
#include "SlidePickerBox.h"
#include <QPainter>
#include <QLayout>
#include <QMouseEvent>
#include <QLabel>
#include <qdebug.h>
const int fontSize = 80;
SlidePickerBox::SlidePickerBox(QWidget *parent):QWidget(parent) {
namespace {
const int LABEL_FONT_SIZE = 80;
const int LABEL_CENTER_Y = 150;
const int LABEL_HEIGHT = 110;
const int LINE_HEIGHT = 100;
const int LABEL_WIDTH = 320;
const int MARGIN_LEFT = 0;
const int MARGIN_TOP = 100;
const int SELECTED_AREA_TOP = 100;
const int SELECTED_AREA_BOTTOM = 200;
}
SlidePickerBox::SlidePickerBox(QWidget *parent)
: QWidget(parent)
, mIsDragging(false)
, mOriginPosY(0)
, mSelectedIndex(0)
, mSelectedLbl(new QLabel(this))
{
this->setFixedHeight(360);
mSelectedLbl->setText("2");
mSelectedLbl->setFixedHeight(LABEL_HEIGHT);
mSelectedLbl->setAlignment(Qt::AlignCenter);
mSelectedLbl->setObjectName("sliderPickerLabel");
mSelectedLbl->setFixedHeight(LABEL_FONT_SIZE);
mSelectedLbl->setFixedWidth(LABEL_WIDTH);
QPoint p1 = {MARGIN_LEFT, LABEL_CENTER_Y - LABEL_FONT_SIZE / 2};
mSelectedLbl->move(p1);
mLabels.push_back(mSelectedLbl);
mSelectedLbl->setStyleSheet("color:white");
QLabel* label = new QLabel(this);
label->setText("1");
label->setFixedHeight(110);
label->setAlignment(Qt::AlignCenter);
label->setObjectName("sliderPickerLabel");
label->setFixedHeight(fontSize);
label->setFixedWidth(320);
QPoint p = {0,50-fontSize/2};
label->move(p);
lbls.push_back(label);
QLabel* label1 = new QLabel(this);
label1->setText("2");
label1->setFixedHeight(110);
label1->setAlignment(Qt::AlignCenter);
label1->setObjectName("sliderPickerLabel");
label1->setFixedHeight(fontSize);
label1->setFixedWidth(320);
QPoint p1 = {0,150-fontSize/2};
label1->move(p1);
lbls.push_back(label1);
QLabel* label2 = new QLabel(this);
label2->setText("3");
label2->setFixedHeight(110);
label2->setAlignment(Qt::AlignCenter);
label2->setObjectName("sliderPickerLabel");
label2->setFixedHeight(fontSize);
label2->setFixedWidth(320);
QPoint p2 = {0,250-fontSize/2};
label2->move(p2);
lbls.push_back(label2);
selectedLbl = label1;
label1->setStyleSheet("color:white");
label->setStyleSheet("background:transparent");
label2->setStyleSheet("background:transparent" );
QWidget* line1 = new QWidget(this);
line1->setFixedSize(320,100);
line1->setObjectName("topBottomLine");
line1->raise();
QPoint lp = {0,100};
line1->move(lp);
selectedIndex = 1;
auto linePlaceholderWidget = new QWidget(this);
linePlaceholderWidget->setFixedSize(LABEL_WIDTH, LINE_HEIGHT);
linePlaceholderWidget->setObjectName("topBottomLine");
linePlaceholderWidget->raise();
QPoint lp = {MARGIN_LEFT, MARGIN_TOP};
linePlaceholderWidget->move(lp);
}
void SlidePickerBox::mousePressEvent(QMouseEvent * ev) {
isDragging = true;
o_x = ev->pos().x();
o_y = ev->pos().y();
mIsDragging = true;
mOriginPosY = ev->pos().y();
QWidget::mousePressEvent( ev);
}
void SlidePickerBox::mouseMoveEvent(QMouseEvent *ev) {
if(lbls.count()<2) return;
if(isDragging)
//只有一个label无需滑动
if (mLabels.count() < 2) return;
if (nullptr == mSelectedLbl) return;
if (mIsDragging)
{
int offset = (ev->pos().y()-o_y);
int offset = (ev->pos().y() - mOriginPosY);
//防止速度过快
while(abs(offset)>50)
{
offset=offset/2;
}
//防止拉过头
int selectItemCenter = selectedLbl->geometry().center().y();
if (selectedLbl == getEnabledLastLabel() && selectItemCenter<=150 && offset<0) return;
if (selectedLbl == getEnabledFirstLabel() && selectItemCenter>=150 && offset>0) return;
int selItemCenterY = mSelectedLbl->geometry().center().y();
if (mSelectedLbl == getEnabledLastLabel() && selItemCenterY <= LABEL_CENTER_Y && offset < 0) return;
if (mSelectedLbl == getEnabledFirstLabel() && selItemCenterY >= LABEL_CENTER_Y && offset > 0) return;
int i = 0;
for (auto item : lbls)
for (auto item : mLabels)
{
if (disableItems.contains(item->text()))continue;
//不需要横向
//int nx = item->geometry().left()+(ev->pos().x()-o_x);
if (mDisabledItems.contains(item->text()))continue;
//不需要横向,只需要纵向
int ny = item->geometry().top() + offset;
item->move(item->geometry().left(),ny);
int nc = item->geometry().center().y();
if (nc<=200 && nc>100)
int centerY = item->geometry().center().y();
if (centerY <= SELECTED_AREA_BOTTOM
&& centerY > SELECTED_AREA_TOP)
{
item->setStyleSheet("color:white");
selectedLbl = item;
selectedIndex = i;
mSelectedLbl = item;
mSelectedIndex = i;
} else{
item->setStyleSheet("background:transparent");
}
i++;
}
o_x = ev->pos().x();
o_y = ev->pos().y();
mOriginPosY = ev->pos().y();
repaint();
}
QWidget::mouseMoveEvent(ev);
}
void SlidePickerBox::mouseReleaseEvent(QMouseEvent *ev) {
isDragging = false;
adjustPositon();
mIsDragging = false;
adjustPosition();
QWidget::mouseReleaseEvent(ev);
QString v = getSelectedValue();
emit valueChanged(v);
}
void SlidePickerBox::adjustPositon() const {
if (selectedLbl->geometry().center().y() != 150)
void SlidePickerBox::adjustPosition() const {
if (mSelectedLbl->geometry().center().y() != LABEL_CENTER_Y)
{
//选择完毕,选中项回归正位
int offset = 150 - selectedLbl->geometry().center().y();
for (auto item : lbls)
int offset = LABEL_CENTER_Y - mSelectedLbl->geometry().center().y();
for (auto item : mLabels)
{
int ny = item->geometry().top()+offset;
item->move(item->geometry().left(),ny);
@@ -129,148 +117,129 @@ void SlidePickerBox::adjustPositon() const {
}
}
void SlidePickerBox::paintEvent(QPaintEvent *ev) {
QWidget::paintEvent(ev);
}
void SlidePickerBox::paintText(QString txt, int x, int y, const QColor& color) {
QPainter painter(this);
painter.setRenderHint(QPainter::TextAntialiasing, true);
QFont f;
f.setPixelSize(30);
painter.setFont(f);
painter.setPen(color);
painter.drawText(x,y,txt);
}
void SlidePickerBox::setItems(const QStringList& itemsList) {
this->items = itemsList;
hideLabel(selectedLbl);
hideLabel(prevLbl);
hideLabel(nextLbl);
for (auto item : lbls)
this->mItems = itemsList;
hideLabel(mSelectedLbl);
for (auto item : mLabels)
{
delete item;
}
selectedLbl = nullptr;
prevLbl = nullptr;
nextLbl = nullptr;
lbls.clear();
for (QString str : this->items)
mSelectedLbl = nullptr;
mLabels.clear();
QPoint p = {MARGIN_LEFT,-LABEL_CENTER_Y};
for (const QString& str : this->mItems)
{
QLabel* lbl = new QLabel(this);
auto lbl = new QLabel(this);
lbl->setText(str);
lbl->setFixedHeight(110);
lbl->setFixedHeight(LABEL_HEIGHT);
lbl->setAlignment(Qt::AlignCenter);
lbl->setObjectName("sliderPickerLabel");
lbl->setFixedHeight(fontSize);
lbl->setFixedWidth(320);
lbls.push_back(lbl);
QPoint p = {0,-150};
lbl->setFixedHeight(LABEL_FONT_SIZE);
lbl->setFixedWidth(LABEL_WIDTH);
mLabels.push_back(lbl);
lbl->move(p);
}
selectedIndex = lbls.count()-1;
setSelectedValue(this->items.last());
mSelectedIndex = mLabels.count() - 1;
setSelectedValue(this->mItems.last());
}
QString SlidePickerBox::getSelectedValue() {
if (!selectedLbl) return "";
return selectedLbl->text();
if (!mSelectedLbl) return "";
return mSelectedLbl->text();
}
void SlidePickerBox::setCurrentLabel(QLabel *label) {
if (selectedLbl)hideLabel(selectedLbl);
if (mSelectedLbl)hideLabel(mSelectedLbl);
if (label) {
QPoint lp = {0, 100};
label->move(lp);
QPoint p = {MARGIN_LEFT, MARGIN_TOP};
label->move(p);
label->show();
selectedLbl = label;
mSelectedLbl = label;
}
}
QLabel * SlidePickerBox::getEnabledFirstLabel() {
if (disableItems.empty()) return lbls.first();
for(int idx = 0; idx<disableItems.size(); idx++){
if(disableItems.contains(lbls[idx]->text()))continue;
return lbls[idx];
if (mDisabledItems.empty()) return mLabels.first();
for(int idx = 0; idx < mDisabledItems.size(); ++idx){
if(mDisabledItems.contains(mLabels[idx]->text()))continue;
return mLabels[idx];
}
return nullptr;
}
QLabel * SlidePickerBox::getEnabledLastLabel() {
if (disableItems.empty()) return lbls.last();
for(int idx = lbls.size()-1; idx>=0; idx--){
if(disableItems.contains(lbls[idx]->text()))continue;
return lbls[idx];
if (mDisabledItems.empty()) return mLabels.last();
for(int idx = mLabels.size() - 1; idx >= 0; --idx){
if(mDisabledItems.contains(mLabels[idx]->text()))continue;
return mLabels[idx];
}
return nullptr;
}
void SlidePickerBox::hideLabel(QLabel *label) {
if (!label) return;
QPoint lp = {0, -150};
label->move(lp);
QPoint p = {MARGIN_LEFT, -LABEL_CENTER_Y};
label->move(p);
}
void SlidePickerBox::setSelectedValue(const QString& val) {
qDebug()<<"set value:"<<val;
for (int i = 0; i < lbls.count() ; ++i) {
if(lbls[i]->text() == val) {
selectedIndex = i;
for (int i = 0; i < mLabels.count() ; ++i) {
if(mLabels[i]->text() == val) {
mSelectedIndex = i;
break;
}
}
int first_y = -100 * (selectedIndex-1);
for (int i = 0; i < lbls.count() ; ++i) {
int firstLabelY = -LABEL_HEIGHT * (mSelectedIndex - 1);
for (int i = 0; i < mLabels.count() ; ++i) {
QPoint lp = this->mapTo(this,{0, first_y+i*100});
lbls[i]->move(lp);
lbls[i]->show();
lbls[i]->setStyleSheet("background:transparent");
QPoint leftPoint = this->mapTo(this, {MARGIN_LEFT, firstLabelY + i * LABEL_HEIGHT});
mLabels[i]->move(leftPoint);
mLabels[i]->show();
mLabels[i]->setStyleSheet("background:transparent");
}
selectedLbl = lbls[selectedIndex];
lbls[selectedIndex]->setStyleSheet("color:white");
adjustPositon();
mSelectedLbl = mLabels[mSelectedIndex];
mLabels[mSelectedIndex]->setStyleSheet("color:white");
adjustPosition();
}
void SlidePickerBox::resizeLabelWidth() {
for (int i = 0; i < lbls.count() ; ++i) {
lbls[i]->setAlignment(defaultAlign);
lbls[i]->setFixedWidth(this->width()+this->contentsMargins().left()+this->contentsMargins().right());
for (int i = 0; i < mLabels.count() ; ++i) {
mLabels[i]->setAlignment(Qt::AlignCenter);
mLabels[i]->setFixedWidth(this->width() + this->contentsMargins().left() + this->contentsMargins().right());
}
}
void SlidePickerBox::disableItem(const QString& val) {
if (!disableItems.contains(val)){
disableItems.append(val);
if (!mDisabledItems.contains(val)){
mDisabledItems.append(val);
rearrangeLabels();
}
}
void SlidePickerBox::enableItem(const QString &val) {
if (disableItems.contains(val)){
disableItems.removeOne(val);
if (mDisabledItems.contains(val)){
mDisabledItems.removeOne(val);
rearrangeLabels();
}
}
void SlidePickerBox::rearrangeLabels() {
int first_y = -100 * (selectedIndex-1);
int r_index = 0;
for (int i = 0; i < lbls.count() ; ++i) {
if (disableItems.contains(lbls[i]->text())){
lbls[i]->hide();
int firstLabelY = -100 * (mSelectedIndex - 1);
int visibleItemIndex = 0;
for (int i = 0; i < mLabels.count() ; ++i) {
if (mDisabledItems.contains(mLabels[i]->text())){
mLabels[i]->hide();
continue;
}
QPoint lp = this->mapTo(this,{0, first_y+r_index*100});
r_index++;
lbls[i]->move(lp);
lbls[i]->show();
lbls[i]->setStyleSheet("background:transparent");
QPoint p = this->mapTo(this, {MARGIN_LEFT, firstLabelY + visibleItemIndex * LABEL_HEIGHT});
visibleItemIndex++;
mLabels[i]->move(p);
mLabels[i]->show();
mLabels[i]->setStyleSheet("background:transparent");
}
selectedLbl = lbls[selectedIndex];
lbls[selectedIndex]->setStyleSheet("color:white");
adjustPositon();
mSelectedLbl = mLabels[mSelectedIndex];
mLabels[mSelectedIndex]->setStyleSheet("color:white");
adjustPosition();
}

View File

@@ -14,50 +14,38 @@ public:
QString getSelectedValue();
void setItems(const QStringList& itemsList);
void addItem(QString& item) {
this->items.append(item);
this->mItems.append(item);
}
void disableItem(const QString& val);
void enableItem(const QString& val);
int getItemsCount(){
return items.size();
return mItems.size();
}
void setSelectedValue(const QString& val);
void resizeLabelWidth();
void setDefaultAlignment(QFlags<Qt::AlignmentFlag> align){
this->defaultAlign = align;
}
signals:
signals:
void valueChanged(QString & value);
protected:
bool isDragging;
// QPropertyAnimation *homingAni;
bool mIsDragging;
void mousePressEvent(QMouseEvent * ev) override ;
void mouseMoveEvent(QMouseEvent * ev) override ;
void mouseReleaseEvent(QMouseEvent * ev) override ;
void paintEvent(QPaintEvent * ev) override ;
void paintText(QString txt,int x, int y, const QColor& color);
void paintText(QString txt,int x, int y){
paintText(txt, x, y, QColor(0,0,0));
}
void setCurrentLabel(QLabel* label);
QLabel * getEnabledLastLabel();
QLabel * getEnabledFirstLabel();
void hideLabel(QLabel* label);
static void hideLabel(QLabel* label);
void rearrangeLabels();
private:
int o_x=0,o_y=10;
int selectedIndex = -1;
QLabel* selectedLbl = nullptr;
QLabel* prevLbl = nullptr;
QLabel* nextLbl = nullptr;
QList<QLabel*> lbls;
QStringList items;
QStringList disableItems;
QFlags<Qt::AlignmentFlag> defaultAlign= Qt::AlignCenter;
void adjustPositon() const;
int mOriginPosY;
int mSelectedIndex;
QLabel* mSelectedLbl;
QList<QLabel*> mLabels;
QStringList mItems;
QStringList mDisabledItems;
void adjustPosition() const;
};