本文将通过对一个基于Qt的轮播选择控件的讲解,帮助你更好地理解如何实现一个自定义的滚动选择器。这个控件非常适合用来展示一个可滚动的选项列表(如颜色选择器、选项列表等),并且它支持平滑的滚动、自动更新字体大小以及透明度变化来增强视觉效果。
1. 项目概述
本项目实现了一个基于Qt的滚动选择控件,其中核心组件有两个类:
- AbstractWheelWidget:这是控件的基类,负责处理基本的事件和滚动逻辑。
- StringWheelWidget:继承自
AbstractWheelWidget
,实现了具体的项显示,支持字符串列表的显示和滚动。
2. 核心代码讲解
2.1 AbstractWheelWidget
- 基类
AbstractWheelWidget
提供了滚动、绘制等基础功能,子类通过继承并重载其中的一些虚函数来实现具体的功能。
关键代码:
class AbstractWheelWidget : public QWidget {
Q_OBJECT
public:
AbstractWheelWidget(bool touch, QWidget *parent = 0);
virtual ~AbstractWheelWidget();
int currentIndex() const;
void setCurrentIndex(int index);
bool event(QEvent*);
void paintEvent(QPaintEvent *e);
virtual void paintItem(QPainter* painter, int index, const QRect &rect) = 0; // 需要子类实现
public slots:
void scrollTo(int index);
signals:
void stopped(int index);
protected:
int m_currentItem; // 当前选中的项
int m_itemOffset; // 项的偏移量
qreal m_lastY; // 上次滚动的y位置
};
代码解释:
currentIndex()
和setCurrentIndex()
:用来获取和设置当前选中的项。paintEvent()
:负责绘制控件内容,确定显示区域和绘制的细节。scrollTo(int index)
:实现平滑滚动到指定的索引。
2.2 StringWheelWidget
- 子类实现
StringWheelWidget
继承自 AbstractWheelWidget
,它实现了具体的滚动项绘制。我们在其中使用了QPainter
来绘制每一项,并根据当前项的距离调整字体大小和透明度,模拟远近效果。
关键代码:
class StringWheelWidget : public AbstractWheelWidget {
Q_OBJECT
public:
StringWheelWidget(bool touch = false);
QStringList items() const;
void setItems(const QStringList &items);
QSize sizeHint() const;
QSize minimumSizeHint() const;
void paintItem(QPainter* painter, int index, const QRect &rect); // 重载绘制函数
int itemHeight() const;
int itemCount() const;
QString currentContent() const;
private:
QStringList m_items; // 存储字符串项
};
代码解释:
setItems(const QStringList &items)
:设置要显示的字符串列表。paintItem()
:实现了如何绘制每一项,控制字体大小和透明度。itemHeight()
和itemCount()
:返回项的高度和项的数量。
2.3 滚动与绘制实现
控件使用 QScroller
来处理滚动事件,并在 paintEvent
函数中根据项的偏移量和位置绘制每一项。
关键代码:
void AbstractWheelWidget::paintEvent(QPaintEvent* event) {
Q_UNUSED(event);
int w = width();
int h = height();
QPainter painter(this);
QPalette palette = QApplication::palette();
QPalette::ColorGroup colorGroup = isEnabled() ? QPalette::Active : QPalette::Disabled;
painter.setClipRect(QRect(0, 0, w, h));
painter.setPen(palette.color(colorGroup, QPalette::ButtonText));
int iH = itemHeight();
int iC = itemCount();
if (iC > 0) {
m_itemOffset = m_itemOffset % iH;
// 绘制每一个可视的项
for (int i = -h / 2 / iH; i <= h / 2 / iH + 1; i++) {
int itemNum = m_currentItem + i;
while (itemNum < 0) itemNum += iC;
while (itemNum >= iC) itemNum -= iC;
paintItem(&painter, itemNum, QRect(6, h / 2 + i * iH - m_itemOffset - iH / 2, w - 6, iH));
}
}
// 绘制选中的中心条
QColor highlight = palette.color(colorGroup, QPalette::Highlight);
highlight.setAlpha(150);
QLinearGradient grad2(0.5, 0, 0.5, 1.0);
grad2.setColorAt(0, highlight);
grad2.setColorAt(1.0, highlight.lighter());
grad2.setCoordinateMode(QGradient::ObjectBoundingMode);
QBrush gBrush2(grad2);
painter.setPen(QPen(QBrush(QColor(Qt::darkGray)), 2));
painter.drawLine(QPoint(0, h / 2 - iH / 2), QPoint(w, h / 2 - iH / 2));
painter.drawLine(QPoint(0, h / 2 + iH / 2), QPoint(w, h / 2 + iH / 2));
}
代码解释:
- 控件会绘制一个选项区域,并根据滚动位置计算每一项的显示位置。
paintItem
函数负责根据项的索引绘制具体的内容,并动态调整字体大小和透明度。
3. 项目效果展示
通过上述代码,我们能够实现一个简单的轮播选择控件,类似于GIF中的效果,用户可以滚动选择不同的项,且当前选中的项会更加突出。具体展示效果如下:
4. 下载链接
你可以通过以下链接下载完整的项目代码:
通过网盘分享的文件:轮播选取其器控件
链接: https://pan.baidu.com/s/1DdAvdmBm3QvN3xWD6RLxMg?pwd=jkcf 提取码: jkcf