260 lines
6.2 KiB
C++
260 lines
6.2 KiB
C++
#include "Carousel.h"
|
|
#include <QContextMenuEvent>
|
|
#include <QDebug>
|
|
|
|
MyCarousel::MyCarousel(QWidget* parent)
|
|
: QWidget(parent),
|
|
m_stackedWidget(new QStackedWidget(this)),
|
|
m_bottomButtonOverlay(nullptr),
|
|
m_bottomButtonLayout(nullptr),
|
|
m_bottomButtonGroup(nullptr),
|
|
m_currentIndex(0),
|
|
m_isPlaying(false),
|
|
m_isLocked(false),
|
|
m_lockedIndex(-1),
|
|
m_playInterval(2000),
|
|
m_intervalButtonSize(40)
|
|
{
|
|
QVBoxLayout* layout = new QVBoxLayout(this);
|
|
layout->addWidget(m_stackedWidget);
|
|
layout->setContentsMargins(0, 0, 0, 0);
|
|
|
|
m_autoPlayerTimer = new QTimer(this);
|
|
connect(m_autoPlayerTimer, &QTimer::timeout,
|
|
this, &MyCarousel::slideRight);
|
|
|
|
m_nomalQSS= R"(
|
|
QPushButton
|
|
{
|
|
background-color: #FFFFFF;
|
|
border-radius: 5px;
|
|
border: 1px solid #FFFFFF;
|
|
}
|
|
QPushButton:checked
|
|
{
|
|
background-color: #08F8E8;
|
|
border-radius: 5px;
|
|
border: 1px solid #08F8E8;
|
|
}
|
|
QPushButton:hover
|
|
{
|
|
background-color: red;
|
|
border-radius: 5px;
|
|
border: 1px solid red;
|
|
}
|
|
/*QPushButton:!checked {
|
|
background-color: #FFFFFF;
|
|
border-radius: 5px;
|
|
border: 1px solid #FFFFFF;
|
|
}*/
|
|
)";
|
|
|
|
m_lockedQSS = R"(
|
|
QPushButton
|
|
{
|
|
background-color: #FFFFFF;
|
|
border-radius: 5px;
|
|
border: 1px solid #FFFFFF;
|
|
}
|
|
QPushButton:checked
|
|
{
|
|
background-color: #08F8E8;
|
|
border-radius: 5px;
|
|
border: 1px solid #08F8E8;
|
|
}
|
|
QPushButton:hover
|
|
{
|
|
background-color: red;
|
|
border-radius: 5px;
|
|
border: 1px solid red;
|
|
}
|
|
)";
|
|
}
|
|
|
|
void MyCarousel::addWidget(QWidget* w)
|
|
{
|
|
m_widgets.append(w);
|
|
m_stackedWidget->addWidget(w);
|
|
updateStackedWidgetVisibility();
|
|
}
|
|
|
|
void MyCarousel::play()
|
|
{
|
|
if (m_widgets.isEmpty())
|
|
return;
|
|
|
|
m_isPlaying = true;
|
|
|
|
// 创建底部按钮
|
|
m_bottomButtonLayout = new QHBoxLayout();
|
|
m_bottomButtonGroup = new QButtonGroup(this);
|
|
m_bottomButtons.clear();
|
|
|
|
for (int i = 0; i < m_widgets.size(); ++i) {
|
|
QPushButton* btn = new QPushButton(this);
|
|
btn->setCheckable(true);
|
|
btn->setFixedSize(m_intervalButtonSize, 3);
|
|
btn->setStyleSheet(m_nomalQSS);
|
|
btn->setFixedHeight(10);
|
|
btn->setFixedWidth(10);
|
|
|
|
m_bottomButtonLayout->addWidget(btn);
|
|
m_bottomButtonGroup->addButton(btn, i);
|
|
m_bottomButtons.append(btn);
|
|
|
|
connect(btn, &QPushButton::clicked, this, [this, i]() {
|
|
onButtonClicked(i);
|
|
});
|
|
}
|
|
|
|
m_bottomButtonOverlay = new QWidget(this);
|
|
m_bottomButtonOverlay->setLayout(m_bottomButtonLayout);
|
|
m_bottomButtonOverlay->setAttribute(Qt::WA_TranslucentBackground);
|
|
m_bottomButtonOverlay->show();
|
|
|
|
m_autoPlayerTimer->setInterval(m_playInterval);
|
|
m_autoPlayerTimer->start();
|
|
|
|
updateStackedWidgetVisibility();
|
|
}
|
|
|
|
void MyCarousel::contextMenuEvent(QContextMenuEvent* event)
|
|
{
|
|
showContextMenu(event->globalPos());
|
|
}
|
|
|
|
void MyCarousel::showContextMenu(const QPoint& pos)
|
|
{
|
|
QMenu menu(this);
|
|
|
|
QAction* startAct = menu.addAction(QString::fromLocal8Bit("开始轮播"));
|
|
QAction* stopAct = menu.addAction(QString::fromLocal8Bit("停止轮播"));
|
|
|
|
if (!m_isLocked)
|
|
startAct->setEnabled(false);
|
|
|
|
if (m_isLocked)
|
|
stopAct->setEnabled(false);
|
|
|
|
QAction* act = menu.exec(pos);
|
|
|
|
if (act == startAct)
|
|
startAutoPlay();
|
|
else if (act == stopAct)
|
|
stopAutoPlay();
|
|
}
|
|
|
|
void MyCarousel::startAutoPlay()
|
|
{
|
|
updateButtonState(m_currentIndex);
|
|
}
|
|
|
|
void MyCarousel::stopAutoPlay()
|
|
{
|
|
updateButtonState(m_currentIndex);
|
|
}
|
|
|
|
void MyCarousel::onButtonClicked(int index)
|
|
{
|
|
updateButtonState(index);
|
|
gotoWidget(index);
|
|
}
|
|
|
|
void MyCarousel::updateButtonState(int index)
|
|
{
|
|
if (m_isLocked)
|
|
{
|
|
if (index == m_lockedIndex) {
|
|
// 解锁
|
|
m_isLocked = false;
|
|
m_lockedIndex = -1;
|
|
|
|
if (m_isPlaying)
|
|
m_autoPlayerTimer->start();
|
|
|
|
restoreButtonStyle(index);
|
|
}
|
|
else {
|
|
// 切换锁定
|
|
restoreButtonStyle(m_lockedIndex);
|
|
setButtonLocked(index);
|
|
m_lockedIndex = index;
|
|
}
|
|
}
|
|
else {
|
|
// 初次锁定
|
|
m_isLocked = true;
|
|
m_lockedIndex = index;
|
|
m_autoPlayerTimer->stop();
|
|
setButtonLocked(index);
|
|
}
|
|
}
|
|
|
|
void MyCarousel::setButtonLocked(int index)
|
|
{
|
|
QPushButton* btn = m_bottomButtons[index];
|
|
btn->setText("");
|
|
btn->setStyleSheet(m_lockedQSS);
|
|
}
|
|
|
|
void MyCarousel::restoreButtonStyle(int index)
|
|
{
|
|
if (index < 0)
|
|
return;
|
|
|
|
QPushButton* btn = m_bottomButtons[index];
|
|
btn->setText("");
|
|
btn->setStyleSheet(m_nomalQSS);
|
|
}
|
|
|
|
void MyCarousel::slideLeft()
|
|
{
|
|
if (m_widgets.isEmpty() || m_isLocked || !m_isPlaying)
|
|
return;
|
|
|
|
m_currentIndex = (m_currentIndex - 1 + m_widgets.size()) % m_widgets.size();
|
|
updateStackedWidgetVisibility();
|
|
}
|
|
|
|
void MyCarousel::slideRight()
|
|
{
|
|
if (m_widgets.isEmpty() || m_isLocked || !m_isPlaying)
|
|
return;
|
|
|
|
m_currentIndex = (m_currentIndex + 1) % m_widgets.size();
|
|
updateStackedWidgetVisibility();
|
|
}
|
|
|
|
void MyCarousel::gotoWidget(int index)
|
|
{
|
|
m_currentIndex = index;
|
|
updateStackedWidgetVisibility();
|
|
}
|
|
|
|
void MyCarousel::updateStackedWidgetVisibility()
|
|
{
|
|
if (m_widgets.isEmpty())
|
|
return;
|
|
|
|
m_stackedWidget->setCurrentIndex(m_currentIndex);
|
|
|
|
if (!m_isLocked) {
|
|
for (int i = 0; i < m_bottomButtons.size(); ++i)
|
|
m_bottomButtons[i]->setChecked(i == m_currentIndex);
|
|
}
|
|
}
|
|
|
|
void MyCarousel::resizeEvent(QResizeEvent*)
|
|
{
|
|
if (!m_bottomButtonOverlay)
|
|
return;
|
|
|
|
int count = m_widgets.size();
|
|
int totalWidth = m_intervalButtonSize * count + 10 * (count - 1);
|
|
|
|
int x = (width() - totalWidth) / 2;
|
|
int y = height() - m_intervalButtonSize;
|
|
|
|
m_bottomButtonOverlay->setGeometry(x, y, totalWidth, m_intervalButtonSize);
|
|
}
|