#include "ElaComboBox.h" #include "ElaComboBoxStyle.h" #include "ElaScrollBar.h" #include "ElaTheme.h" #include "private/ElaComboBoxPrivate.h" #include #include #include #include #include #include #include Q_PROPERTY_CREATE_Q_CPP(ElaComboBox, int, BorderRadius) ElaComboBox::ElaComboBox(QWidget* parent) : QComboBox(parent), d_ptr(new ElaComboBoxPrivate()) { Q_D(ElaComboBox); d->q_ptr = this; d->_pBorderRadius = 3; d->_themeMode = eTheme->getThemeMode(); setObjectName("ElaComboBox"); setFixedHeight(35); d->_comboBoxStyle = new ElaComboBoxStyle(style()); setStyle(d->_comboBoxStyle); //调用view 让container初始化 setView(new QListView(this)); QAbstractItemView* comboBoxView = this->view(); comboBoxView->setVerticalScrollMode(QAbstractItemView::ScrollPerPixel); ElaScrollBar* scrollBar = new ElaScrollBar(this); comboBoxView->setVerticalScrollBar(scrollBar); ElaScrollBar* floatVScrollBar = new ElaScrollBar(scrollBar, comboBoxView); floatVScrollBar->setIsAnimation(true); comboBoxView->setAutoScroll(false); comboBoxView->setSelectionMode(QAbstractItemView::NoSelection); comboBoxView->setObjectName("ElaComboBoxView"); comboBoxView->setStyleSheet("#ElaComboBoxView{background-color:transparent;}"); comboBoxView->setStyle(d->_comboBoxStyle); QWidget* container = this->findChild(); if (container) { container->setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::NoDropShadowWindowHint); container->setAttribute(Qt::WA_TranslucentBackground); container->setObjectName("ElaComboBoxContainer"); container->setStyle(d->_comboBoxStyle); QLayout* layout = container->layout(); while (layout->count()) { layout->takeAt(0); } layout->addWidget(view()); layout->setContentsMargins(6, 0, 6, 6); #ifndef Q_OS_WIN #if QT_VERSION >= QT_VERSION_CHECK(6, 0, 0) container->setStyleSheet("background-color:transparent;"); #endif #endif } QComboBox::setMaxVisibleItems(5); connect(eTheme, &ElaTheme::themeModeChanged, d, &ElaComboBoxPrivate::onThemeChanged); } ElaComboBox::~ElaComboBox() { Q_D(ElaComboBox); delete d->_comboBoxStyle; } void ElaComboBox::setEditable(bool editable) { Q_D(ElaComboBox); QComboBox::setEditable(editable); if (editable) { lineEdit()->setStyle(d->_comboBoxStyle); d->onThemeChanged(d->_themeMode); } } void ElaComboBox::showPopup() { Q_D(ElaComboBox); bool oldAnimationEffects = qApp->isEffectEnabled(Qt::UI_AnimateCombo); qApp->setEffectEnabled(Qt::UI_AnimateCombo, false); QComboBox::showPopup(); qApp->setEffectEnabled(Qt::UI_AnimateCombo, oldAnimationEffects); if (count() > 0) { QWidget* container = this->findChild(); if (container) { int containerHeight = 0; if (count() >= maxVisibleItems()) { containerHeight = maxVisibleItems() * 35 + 8; } else { containerHeight = count() * 35 + 8; } view()->resize(view()->width(), containerHeight - 8); container->move(container->x(), container->y() + 3); QLayout* layout = container->layout(); while (layout->count()) { layout->takeAt(0); } QPropertyAnimation* fixedSizeAnimation = new QPropertyAnimation(container, "maximumHeight"); connect(fixedSizeAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { container->setFixedHeight(value.toUInt()); }); fixedSizeAnimation->setStartValue(1); fixedSizeAnimation->setEndValue(containerHeight); fixedSizeAnimation->setEasingCurve(QEasingCurve::OutCubic); fixedSizeAnimation->setDuration(400); fixedSizeAnimation->start(QAbstractAnimation::DeleteWhenStopped); QPropertyAnimation* viewPosAnimation = new QPropertyAnimation(view(), "pos"); connect(viewPosAnimation, &QPropertyAnimation::finished, this, [=]() { d->_isAllowHidePopup = true; layout->addWidget(view()); }); QPoint viewPos = view()->pos(); viewPosAnimation->setStartValue(QPoint(viewPos.x(), viewPos.y() - view()->height())); viewPosAnimation->setEndValue(viewPos); viewPosAnimation->setEasingCurve(QEasingCurve::OutCubic); viewPosAnimation->setDuration(400); viewPosAnimation->start(QAbstractAnimation::DeleteWhenStopped); } //指示器动画 QPropertyAnimation* rotateAnimation = new QPropertyAnimation(d->_comboBoxStyle, "pExpandIconRotate"); connect(rotateAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { update(); }); rotateAnimation->setDuration(300); rotateAnimation->setEasingCurve(QEasingCurve::InOutSine); rotateAnimation->setStartValue(d->_comboBoxStyle->getExpandIconRotate()); rotateAnimation->setEndValue(-180); rotateAnimation->start(QAbstractAnimation::DeleteWhenStopped); QPropertyAnimation* markAnimation = new QPropertyAnimation(d->_comboBoxStyle, "pExpandMarkWidth"); markAnimation->setDuration(300); markAnimation->setEasingCurve(QEasingCurve::InOutSine); markAnimation->setStartValue(d->_comboBoxStyle->getExpandMarkWidth()); markAnimation->setEndValue(width() / 2 - d->_pBorderRadius - 6); markAnimation->start(QAbstractAnimation::DeleteWhenStopped); } } void ElaComboBox::hidePopup() { Q_D(ElaComboBox); if (d->_isAllowHidePopup) { QWidget* container = this->findChild(); int containerHeight = container->height(); if (container) { QLayout* layout = container->layout(); while (layout->count()) { layout->takeAt(0); } QPropertyAnimation* viewPosAnimation = new QPropertyAnimation(view(), "pos"); connect(viewPosAnimation, &QPropertyAnimation::finished, this, [=]() { layout->addWidget(view()); QMouseEvent focusEvent(QEvent::MouseButtonPress, QPoint(-1, -1), QPoint(-1, -1), Qt::NoButton, Qt::NoButton, Qt::NoModifier); QApplication::sendEvent(parentWidget(), &focusEvent); QComboBox::hidePopup(); container->setFixedHeight(containerHeight); }); QPoint viewPos = view()->pos(); connect(viewPosAnimation, &QPropertyAnimation::finished, this, [=]() { view()->move(viewPos); }); viewPosAnimation->setStartValue(viewPos); viewPosAnimation->setEndValue(QPoint(viewPos.x(), viewPos.y() - view()->height())); viewPosAnimation->setEasingCurve(QEasingCurve::InCubic); viewPosAnimation->start(QAbstractAnimation::DeleteWhenStopped); QPropertyAnimation* fixedSizeAnimation = new QPropertyAnimation(container, "maximumHeight"); connect(fixedSizeAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { container->setFixedHeight(value.toUInt()); }); fixedSizeAnimation->setStartValue(container->height()); fixedSizeAnimation->setEndValue(1); fixedSizeAnimation->setEasingCurve(QEasingCurve::InCubic); fixedSizeAnimation->start(QAbstractAnimation::DeleteWhenStopped); d->_isAllowHidePopup = false; } //指示器动画 QPropertyAnimation* rotateAnimation = new QPropertyAnimation(d->_comboBoxStyle, "pExpandIconRotate"); connect(rotateAnimation, &QPropertyAnimation::valueChanged, this, [=](const QVariant& value) { update(); }); rotateAnimation->setDuration(300); rotateAnimation->setEasingCurve(QEasingCurve::InOutSine); rotateAnimation->setStartValue(d->_comboBoxStyle->getExpandIconRotate()); rotateAnimation->setEndValue(0); rotateAnimation->start(QAbstractAnimation::DeleteWhenStopped); QPropertyAnimation* markAnimation = new QPropertyAnimation(d->_comboBoxStyle, "pExpandMarkWidth"); markAnimation->setDuration(300); markAnimation->setEasingCurve(QEasingCurve::InOutSine); markAnimation->setStartValue(d->_comboBoxStyle->getExpandMarkWidth()); markAnimation->setEndValue(0); markAnimation->start(QAbstractAnimation::DeleteWhenStopped); } } void ElaComboBox::paintEvent(QPaintEvent* event) { Q_D(ElaComboBox); if (lineEdit() && lineEdit()->palette().color(QPalette::Text) != ElaThemeColor(d->_themeMode, BasicText)) { d->onThemeChanged(d->_themeMode); } QComboBox::paintEvent(event); }