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

View File

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