feat: Improve date picker, add select item loop logic
This commit is contained in:
@@ -13,11 +13,15 @@ DateSlidePickerBox::DateSlidePickerBox(QWidget *parent)
|
||||
initBox(mHundredYearBox, {"19", "20"}, 56);
|
||||
|
||||
QStringList tenYearValues{"0", "1", "2", "3", "4", "5", "6", "7", "8", "9"};
|
||||
mTenYearBox->setLoop(true);
|
||||
mYearBox->setLoop(true);
|
||||
|
||||
initBox(mTenYearBox, tenYearValues);
|
||||
initBox(mYearBox, tenYearValues);
|
||||
|
||||
addSplitLabel();
|
||||
|
||||
mMonthBox->setLoop(true);
|
||||
QStringList monthValues{"01", "02", "03", "04", "05", "06", "07", "08", "09", "10", "11", "12"};
|
||||
initBox(mMonthBox, monthValues, 56);
|
||||
|
||||
@@ -27,6 +31,7 @@ DateSlidePickerBox::DateSlidePickerBox(QWidget *parent)
|
||||
for (int i = 13; i <= 31; i++) {
|
||||
days << QString("%1").arg(i, 2);
|
||||
}
|
||||
mDayBox->setLoop(true);
|
||||
initBox(mDayBox, days, 56);
|
||||
|
||||
mBigMonthList.append({"01", "03", "05", "07", "08", "10", "12"});
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
#include <QLabel>
|
||||
#include <qdebug.h>
|
||||
|
||||
|
||||
namespace {
|
||||
namespace
|
||||
{
|
||||
const int LABEL_FONT_SIZE = 80;
|
||||
const int LABEL_CENTER_Y = 150;
|
||||
const int LABEL_HEIGHT = 110;
|
||||
@@ -19,11 +19,7 @@ namespace {
|
||||
const int SELECTED_AREA_BOTTOM = 200;
|
||||
}
|
||||
SlidePickerBox::SlidePickerBox(QWidget *parent)
|
||||
: QWidget(parent)
|
||||
, mIsDragging(false)
|
||||
, mOriginPosY(0)
|
||||
, mSelectedIndex(0)
|
||||
, mSelectedLbl(new QLabel(this))
|
||||
: QWidget(parent), mIsDragging(false), mOriginPosY(0), mSelectedIndex(0), mLoopItem(false), mSelectedLbl(new QLabel(this))
|
||||
{
|
||||
this->setFixedHeight(360);
|
||||
mSelectedLbl->setText("2");
|
||||
@@ -45,46 +41,115 @@ SlidePickerBox::SlidePickerBox(QWidget *parent)
|
||||
linePlaceholderWidget->move(lp);
|
||||
}
|
||||
|
||||
void SlidePickerBox::mousePressEvent(QMouseEvent * ev) {
|
||||
void SlidePickerBox::mousePressEvent(QMouseEvent *ev)
|
||||
{
|
||||
mIsDragging = true;
|
||||
mOriginPosY = ev->pos().y();
|
||||
QWidget::mousePressEvent( ev);
|
||||
QWidget::mousePressEvent(ev);
|
||||
}
|
||||
|
||||
void SlidePickerBox::mouseMoveEvent(QMouseEvent *ev) {
|
||||
//只有一个label,无需滑动
|
||||
if (mLabels.count() < 2) return;
|
||||
if (nullptr == mSelectedLbl) return;
|
||||
void SlidePickerBox::mouseMoveEvent(QMouseEvent *ev)
|
||||
{
|
||||
// 只有一个label,无需滑动
|
||||
if (mLabels.count() < 2)
|
||||
return;
|
||||
if (nullptr == mSelectedLbl)
|
||||
return;
|
||||
if (mIsDragging)
|
||||
{
|
||||
int offset = (ev->pos().y() - mOriginPosY);
|
||||
//防止速度过快
|
||||
while(abs(offset)>50)
|
||||
// 防止速度过快
|
||||
while (abs(offset) > 50)
|
||||
{
|
||||
offset=offset/2;
|
||||
offset = offset / 2;
|
||||
}
|
||||
//防止拉过头
|
||||
// 防止拉过头
|
||||
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 : mLabels)
|
||||
if (!mLoopItem || mLabels.count() < 3)
|
||||
{
|
||||
if (mDisabledItems.contains(item->text()))continue;
|
||||
//不需要横向,只需要纵向
|
||||
int ny = item->geometry().top() + offset;
|
||||
item->move(item->geometry().left(),ny);
|
||||
int centerY = item->geometry().center().y();
|
||||
if (centerY <= SELECTED_AREA_BOTTOM+5
|
||||
&& centerY > SELECTED_AREA_TOP-5)
|
||||
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 : mLabels)
|
||||
{
|
||||
item->setStyleSheet("color:white");
|
||||
mSelectedLbl = item;
|
||||
mSelectedIndex = i;
|
||||
} else{
|
||||
item->setStyleSheet("background:transparent");
|
||||
if (mDisabledItems.contains(item->text()))
|
||||
continue;
|
||||
// 不需要横向,只需要纵向
|
||||
int ny = item->geometry().top() + offset;
|
||||
item->move(item->geometry().left(), ny);
|
||||
int centerY = item->geometry().center().y();
|
||||
// new in selectd area
|
||||
if (centerY <= SELECTED_AREA_BOTTOM + 5 && centerY > SELECTED_AREA_TOP - 5)
|
||||
{
|
||||
item->setStyleSheet("color:white");
|
||||
mSelectedLbl = item;
|
||||
mSelectedIndex = i;
|
||||
}
|
||||
else
|
||||
{
|
||||
item->setStyleSheet("background:transparent");
|
||||
}
|
||||
i++;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int newSelectedIndex = 0;
|
||||
for (int i = 0; i<mLabels.count(); i++)
|
||||
{
|
||||
if (mDisabledItems.contains(mLabels[i]->text()))
|
||||
continue;
|
||||
// 不需要横向,只需要纵向
|
||||
int ny = mLabels[i]->geometry().top() + offset;
|
||||
mLabels[i]->move(mLabels[i]->geometry().left(), ny);
|
||||
int centerY = mLabels[i]->geometry().center().y();
|
||||
// new in selectd area
|
||||
if (centerY <= SELECTED_AREA_BOTTOM + 5 && centerY > SELECTED_AREA_TOP - 5)
|
||||
{
|
||||
mSelectedLbl->setStyleSheet("background:transparent");
|
||||
mSelectedLbl = mLabels[i];
|
||||
newSelectedIndex = i;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
mSelectedLbl->setStyleSheet("color:white");
|
||||
if (newSelectedIndex > mSelectedIndex)
|
||||
{
|
||||
auto lastVisibelBack = mLabels.back();
|
||||
int i = mLabels.length()-2;
|
||||
while (!lastVisibelBack->isVisible())
|
||||
{
|
||||
lastVisibelBack = mLabels[i--];
|
||||
}
|
||||
do
|
||||
{
|
||||
auto first = mLabels.first();
|
||||
mLabels.pop_front();
|
||||
mLabels.push_back(first);
|
||||
} while (!mLabels.back()->isVisible());
|
||||
mLabels.back()->move(lastVisibelBack->geometry().left(),
|
||||
lastVisibelBack->geometry().top()+LABEL_HEIGHT);
|
||||
}
|
||||
else if(newSelectedIndex < mSelectedIndex)
|
||||
{
|
||||
auto lastVisibelFirst = mLabels.first();
|
||||
int i = 1;
|
||||
while (!lastVisibelFirst->isVisible())
|
||||
{
|
||||
lastVisibelFirst = mLabels[i++];
|
||||
}
|
||||
do
|
||||
{
|
||||
auto back = mLabels.back();
|
||||
mLabels.pop_back();
|
||||
mLabels.push_front(back);
|
||||
} while (!mLabels.first()->isVisible());
|
||||
mLabels.first()->move(lastVisibelFirst->geometry().left(),
|
||||
lastVisibelFirst->geometry().top()-LABEL_HEIGHT);
|
||||
}
|
||||
i++;
|
||||
}
|
||||
mOriginPosY = ev->pos().y();
|
||||
repaint();
|
||||
@@ -92,33 +157,36 @@ void SlidePickerBox::mouseMoveEvent(QMouseEvent *ev) {
|
||||
QWidget::mouseMoveEvent(ev);
|
||||
}
|
||||
|
||||
void SlidePickerBox::mouseReleaseEvent(QMouseEvent *ev) {
|
||||
void SlidePickerBox::mouseReleaseEvent(QMouseEvent *ev)
|
||||
{
|
||||
mIsDragging = false;
|
||||
adjustPosition();
|
||||
QWidget::mouseReleaseEvent(ev);
|
||||
QString v = getSelectedValue();
|
||||
emit valueChanged(v);
|
||||
}
|
||||
void SlidePickerBox::adjustPosition() const
|
||||
{
|
||||
|
||||
void SlidePickerBox::adjustPosition() const {
|
||||
if(mSelectedLbl == nullptr)
|
||||
if (mSelectedLbl == nullptr)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (mSelectedLbl->geometry().center().y() != LABEL_CENTER_Y)
|
||||
{
|
||||
//选择完毕,选中项回归正位
|
||||
// 选择完毕,选中项回归正位
|
||||
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);
|
||||
int ny = item->geometry().top() + offset;
|
||||
item->move(item->geometry().left(), ny);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void SlidePickerBox::setItems(const QStringList& itemsList) {
|
||||
void SlidePickerBox::setItems(const QStringList &itemsList)
|
||||
{
|
||||
this->mItems = itemsList;
|
||||
hideLabel(mSelectedLbl);
|
||||
for (auto item : mLabels)
|
||||
@@ -127,8 +195,8 @@ void SlidePickerBox::setItems(const QStringList& itemsList) {
|
||||
}
|
||||
mSelectedLbl = nullptr;
|
||||
mLabels.clear();
|
||||
QPoint p = {MARGIN_LEFT,-LABEL_CENTER_Y};
|
||||
for (const QString& str : this->mItems)
|
||||
QPoint p = {MARGIN_LEFT, -LABEL_CENTER_Y};
|
||||
for (const QString &str : this->mItems)
|
||||
{
|
||||
auto lbl = new QLabel(this);
|
||||
lbl->setText(str);
|
||||
@@ -140,21 +208,42 @@ void SlidePickerBox::setItems(const QStringList& itemsList) {
|
||||
mLabels.push_back(lbl);
|
||||
lbl->move(p);
|
||||
}
|
||||
mSelectedIndex = mLabels.count() - 1;
|
||||
if(!mItems.isEmpty())
|
||||
if (!mLoopItem || mLabels.count() <= 3)
|
||||
{
|
||||
setSelectedValue(this->mItems.last());
|
||||
mSelectedIndex = mLabels.count() - 1;
|
||||
if (!mItems.isEmpty())
|
||||
{
|
||||
setSelectedValue(this->mItems.last());
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSelectedIndex = (mLabels.count() + 1) / 2;
|
||||
if (!mItems.isEmpty())
|
||||
{
|
||||
setSelectedValue(mLabels[mSelectedIndex]->text());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QString SlidePickerBox::getSelectedValue() {
|
||||
if (!mSelectedLbl) return "";
|
||||
void SlidePickerBox::setLoop(bool aIsLoop)
|
||||
{
|
||||
mLoopItem = aIsLoop;
|
||||
}
|
||||
|
||||
QString SlidePickerBox::getSelectedValue()
|
||||
{
|
||||
if (!mSelectedLbl)
|
||||
return "";
|
||||
return mSelectedLbl->text();
|
||||
}
|
||||
|
||||
void SlidePickerBox::setCurrentLabel(QLabel *label) {
|
||||
if (mSelectedLbl)hideLabel(mSelectedLbl);
|
||||
if (label) {
|
||||
void SlidePickerBox::setCurrentLabel(QLabel *label)
|
||||
{
|
||||
if (mSelectedLbl)
|
||||
hideLabel(mSelectedLbl);
|
||||
if (label)
|
||||
{
|
||||
QPoint p = {MARGIN_LEFT, MARGIN_TOP};
|
||||
label->move(p);
|
||||
label->show();
|
||||
@@ -162,47 +251,92 @@ void SlidePickerBox::setCurrentLabel(QLabel *label) {
|
||||
}
|
||||
}
|
||||
|
||||
QLabel * SlidePickerBox::getEnabledFirstLabel() {
|
||||
if (mDisabledItems.empty()) return mLabels.first();
|
||||
for(int idx = 0; idx < mDisabledItems.size(); ++idx){
|
||||
if(mDisabledItems.contains(mLabels[idx]->text()))continue;
|
||||
QLabel *SlidePickerBox::getEnabledFirstLabel()
|
||||
{
|
||||
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 (mDisabledItems.empty()) return mLabels.last();
|
||||
for(int idx = mLabels.size() - 1; idx >= 0; --idx){
|
||||
if(mDisabledItems.contains(mLabels[idx]->text()))continue;
|
||||
QLabel *SlidePickerBox::getEnabledLastLabel()
|
||||
{
|
||||
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;
|
||||
void SlidePickerBox::hideLabel(QLabel *label)
|
||||
{
|
||||
if (!label)
|
||||
return;
|
||||
QPoint p = {MARGIN_LEFT, -LABEL_CENTER_Y};
|
||||
label->move(p);
|
||||
}
|
||||
|
||||
void SlidePickerBox::setSelectedValue(const QString& val) {
|
||||
for (int i = 0; i < mLabels.count() ; ++i) {
|
||||
if(mLabels[i]->text() == val) {
|
||||
mSelectedIndex = i;
|
||||
break;
|
||||
void SlidePickerBox::setSelectedValue(const QString &val)
|
||||
{
|
||||
if (!mLoopItem || mLabels.count() <= 3)
|
||||
{
|
||||
for (int i = 0; i < mLabels.count(); ++i)
|
||||
{
|
||||
if (mLabels[i]->text() == val)
|
||||
{
|
||||
mSelectedIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
int firstLabelY = -LABEL_HEIGHT * (mSelectedIndex - 1);
|
||||
for (int i = 0; i < mLabels.count() ; ++i) {
|
||||
else
|
||||
{
|
||||
int newSelectIndex = 0;
|
||||
for (int i = 0; i < mLabels.count(); ++i)
|
||||
{
|
||||
if (mLabels[i]->text() == val)
|
||||
{
|
||||
newSelectIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
bool step = newSelectIndex > mSelectedIndex;
|
||||
int round = abs(newSelectIndex - mSelectedIndex);
|
||||
for (int i = 0; i < round; i++)
|
||||
{
|
||||
if (step)
|
||||
{
|
||||
auto item = mLabels.first();
|
||||
mLabels.pop_front();
|
||||
mLabels.push_back(item);
|
||||
}
|
||||
else
|
||||
{
|
||||
auto item = mLabels.back();
|
||||
mLabels.pop_back();
|
||||
mLabels.push_front(item);
|
||||
}
|
||||
}
|
||||
}
|
||||
int firstLabelY = -LABEL_HEIGHT * (mSelectedIndex-1);
|
||||
for (int i = 0; i < mLabels.count(); ++i)
|
||||
{
|
||||
|
||||
QPoint leftPoint = this->mapTo(this, {MARGIN_LEFT, firstLabelY + i * LABEL_HEIGHT});
|
||||
mLabels[i]->move(leftPoint);
|
||||
mLabels[i]->show();
|
||||
mLabels[i]->setStyleSheet("background:transparent");
|
||||
|
||||
}
|
||||
if(mSelectedIndex >= 0)
|
||||
if (mSelectedIndex >= 0)
|
||||
{
|
||||
mSelectedLbl = mLabels[mSelectedIndex];
|
||||
mLabels[mSelectedIndex]->setStyleSheet("color:white");
|
||||
@@ -210,33 +344,42 @@ void SlidePickerBox::setSelectedValue(const QString& val) {
|
||||
adjustPosition();
|
||||
}
|
||||
|
||||
void SlidePickerBox::resizeLabelWidth() {
|
||||
for (int i = 0; i < mLabels.count() ; ++i) {
|
||||
void SlidePickerBox::resizeLabelWidth()
|
||||
{
|
||||
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 (!mDisabledItems.contains(val)){
|
||||
void SlidePickerBox::disableItem(const QString &val)
|
||||
{
|
||||
if (!mDisabledItems.contains(val))
|
||||
{
|
||||
mDisabledItems.append(val);
|
||||
rearrangeLabels();
|
||||
}
|
||||
}
|
||||
|
||||
void SlidePickerBox::enableItem(const QString &val) {
|
||||
if (mDisabledItems.contains(val)){
|
||||
void SlidePickerBox::enableItem(const QString &val)
|
||||
{
|
||||
if (mDisabledItems.contains(val))
|
||||
{
|
||||
mDisabledItems.removeOne(val);
|
||||
rearrangeLabels();
|
||||
}
|
||||
}
|
||||
|
||||
void SlidePickerBox::rearrangeLabels() {
|
||||
void SlidePickerBox::rearrangeLabels()
|
||||
{
|
||||
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();
|
||||
for (int i = 0; i < mLabels.count(); ++i)
|
||||
{
|
||||
if (mDisabledItems.contains(mLabels[i]->text()))
|
||||
{
|
||||
mLabels[i]->setVisible(false);
|
||||
continue;
|
||||
}
|
||||
QPoint p = this->mapTo(this, {MARGIN_LEFT, firstLabelY + visibleItemIndex * LABEL_HEIGHT});
|
||||
@@ -249,4 +392,3 @@ void SlidePickerBox::rearrangeLabels() {
|
||||
mLabels[mSelectedIndex]->setStyleSheet("color:white");
|
||||
adjustPosition();
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
#define GUI_SLIDEPICKERBOX_H
|
||||
|
||||
#include <QWidget>
|
||||
#include <QLinkedList>
|
||||
class QLabel;
|
||||
class SlidePickerBox:public QWidget {
|
||||
Q_OBJECT
|
||||
@@ -9,6 +10,8 @@ public:
|
||||
explicit SlidePickerBox(QWidget *parent = nullptr);
|
||||
QString getSelectedValue();
|
||||
void setItems(const QStringList& itemsList);
|
||||
void setLoop(bool isLoop);
|
||||
|
||||
void addItem(QString& item) {
|
||||
this->mItems.append(item);
|
||||
}
|
||||
@@ -37,6 +40,7 @@ protected:
|
||||
private:
|
||||
int mOriginPosY;
|
||||
int mSelectedIndex;
|
||||
bool mLoopItem;
|
||||
QLabel* mSelectedLbl;
|
||||
QList<QLabel*> mLabels;
|
||||
QStringList mItems;
|
||||
|
||||
Reference in New Issue
Block a user