找回密码
 立即注册
收起左侧

Qt编写自定义控件23-广告轮播控件

0
回复
105
查看
[复制链接]
累计签到:7 天
连续签到:1 天
来源: 2019-6-7 10:36:37 显示全部楼层 |阅读模式
一、前言
广告轮播这个控件做的比较早,是很早以前定制一个电信客户端时候用到的,该客户端需要在首页展示轮播预先设定好的图片,图片的路径可以自由设定,然后轮播的间隔速度可以自由控制,同时该控件还需要提供两种指示器的风格,一种是迷你型的样式,一种是数字型的样式。
本控件很早就做好了,由于当时的QPainter功力不足,还不是很熟悉QPainter,采用的是效率比较低的直接用现有控件堆积而成,比如指示器采用的QLabel,用样式表来控制对应的形状,指示器所在的底部放一个widget,采用左右布局,然后右侧放一个弹簧把指示器label全部顶在左边,至于图片的显示,采用的是样式表中的border-image来设置,开个定时器,到了时间则设置成不同的border-image即可。这种方法虽然效率低了点,但是初学者很容易理解接收,甚至可以做出更多的效果,只要项目对CPU要求不高,也不失为一种还行的办法。

二、实现的功能
* 1:可设置显示的图像
* 2:可添加多个广告
* 3:可设置指示器样式 迷你型样式 数字型样式
* 4:可设置指示器大小
* 5:可设置切换间隔

三、效果图


四、头文件代码
  1. #ifndef ADSWIDGET_H
  2. #define ADSWIDGET_H

  3. /**
  4. * 广告轮播控件 作者:feiyangqingyun(QQ:517216493) 2016-12-22
  5. * 1:可设置显示的图像
  6. * 2:可添加多个广告
  7. * 3:可设置指示器样式 迷你型样式 数字型样式
  8. * 4:可设置指示器大小
  9. * 5:可设置切换间隔
  10. */

  11. #include <QWidget>

  12. class QLabel;

  13. #ifdef quc
  14. #if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
  15. #include <QtDesigner/QDesignerExportWidget>
  16. #else
  17. #include <QtUiPlugin/QDesignerExportWidget>
  18. #endif

  19. class QDESIGNER_WIDGET_EXPORT AdsWidget : public QWidget
  20. #else
  21. class AdsWidget : public QWidget
  22. #endif

  23. {
  24.     Q_OBJECT
  25.     Q_ENUMS(BannerStyle)

  26.     Q_PROPERTY(int interval READ getInterval WRITE setInterval)
  27.     Q_PROPERTY(QSize bannerFixedSize READ getBannerFixedSize WRITE setBannerFixedSize)   
  28.     Q_PROPERTY(QString imageNames READ getImageNames WRITE setImageNames)
  29.     Q_PROPERTY(BannerStyle bannerStyle READ getBannerStyle WRITE setBannerStyle)

  30. public:
  31.     enum BannerStyle {
  32.         BannerStyle_Min = 0,    //迷你型样式
  33.         BannerStyle_Num = 1     //数字型样式
  34.     };

  35.     explicit AdsWidget(QWidget *parent = 0);
  36.     ~AdsWidget();

  37. protected:
  38.     bool eventFilter(QObject *obj, QEvent *event);

  39. private:
  40.     int interval;               //自动切换间隔
  41.     QSize bannerFixedSize;      //导航指示器固定尺寸
  42.     BannerStyle bannerStyle;    //导航指示器样式
  43.     QString imageNames;         //导航图片集合字符串

  44.     int currentIndex;           //当前显示的广告对应索引
  45.     QTimer *timer;              //定时器轮播广告
  46.     QList<QLabel *> labs;       //导航标签链表
  47.     QList<QString> names;       //导航图片链表

  48.     QWidget *widgetBg;          //存放广告图片的容器
  49.     QWidget *widgetBanner;      //存放导航指示器的容器

  50. private slots:
  51.     void initWidget();
  52.     void initForm();
  53.     void changedAds();
  54.     void changedAds(QLabel *lab);

  55. public:
  56.     int getInterval()               const;
  57.     QSize getBannerFixedSize()      const;
  58.     BannerStyle getBannerStyle()    const;
  59.     QString getImageNames()         const;

  60.     QSize sizeHint()                const;
  61.     QSize minimumSizeHint()         const;

  62. public Q_SLOTS:
  63.     void setInterval(int interval);
  64.     void setBannerFixedSize(const QSize &bannerFixedSize);
  65.     void setBannerStyle(const BannerStyle &bannerStyle);
  66.     void setImageNames(const QString &imageNames);
  67. };

  68. #endif // ADSWIDGET_H
复制代码


五、完整代码
  1. #pragma execution_character_set("utf-8")

  2. #include "adswidget.h"
  3. #include "qevent.h"
  4. #include "qlabel.h"
  5. #include "qlayout.h"
  6. #include "qtimer.h"
  7. #include "qdebug.h"

  8. AdsWidget::AdsWidget(QWidget *parent) : QWidget(parent)
  9. {
  10.     this->initWidget();
  11.     this->initForm();
  12. }

  13. AdsWidget::~AdsWidget()
  14. {
  15.     if (timer->isActive()) {
  16.         timer->stop();
  17.     }
  18. }

  19. bool AdsWidget::eventFilter(QObject *obj, QEvent *event)
  20. {
  21.     if (event->type() == QEvent::MouseButtonPress) {
  22.         if (obj->inherits("QLabel")) {
  23.             //先停止定时器,防止按下切换的时候短时间内再度切换
  24.             timer->stop();
  25.             changedAds((QLabel *)obj);
  26.             timer->start(interval);
  27.         }
  28.     }

  29.     return QWidget::eventFilter(obj, event);
  30. }

  31. void AdsWidget::initWidget()
  32. {
  33.     QVBoxLayout *verticalLayout = new QVBoxLayout(this);
  34.     verticalLayout->setSpacing(0);
  35.     verticalLayout->setContentsMargins(0, 0, 0, 0);

  36.     widgetBg = new QWidget(this);
  37.     widgetBg->setObjectName(QString::fromUtf8("widgetBg"));

  38.     QGridLayout *gridLayout = new QGridLayout(widgetBg);
  39.     gridLayout->setSpacing(0);
  40.     gridLayout->setContentsMargins(0, 0, 0, 0);

  41.     QSpacerItem *verticalSpacer = new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
  42.     gridLayout->addItem(verticalSpacer, 0, 0, 1, 1);

  43.     widgetBanner = new QWidget(widgetBg);
  44.     widgetBanner->setObjectName(QString::fromUtf8("widgetBanner"));

  45.     QHBoxLayout *horizontalLayout = new QHBoxLayout(widgetBanner);
  46.     horizontalLayout->setSpacing(3);
  47.     gridLayout->addWidget(widgetBanner, 1, 0, 1, 1);

  48.     QSpacerItem *horizontalSpacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
  49.     gridLayout->addItem(horizontalSpacer, 1, 1, 1, 1);
  50.     verticalLayout->addWidget(widgetBg);
  51. }

  52. void AdsWidget::initForm()
  53. {
  54.     interval = 3000;
  55.     bannerFixedSize = QSize(20, 20);
  56.     bannerStyle = BannerStyle_Num;
  57.     imageNames.clear();

  58.     currentIndex = 0;
  59.     timer = new QTimer(this);
  60.     timer->setInterval(interval);
  61.     connect(timer, SIGNAL(timeout()), this, SLOT(changedAds()));
  62.     timer->start();
  63. }

  64. void AdsWidget::changedAds()
  65. {
  66.     if (names.count() == 0) {
  67.         return;
  68.     }

  69.     if (currentIndex < names.count() - 1) {
  70.         currentIndex++;
  71.     } else {
  72.         currentIndex = 0;
  73.     }

  74.     changedAds(labs.at(currentIndex));
  75. }

  76. void AdsWidget::changedAds(QLabel *lab)
  77. {
  78.     //这里采用样式改变背景颜色的方式,也可以改成贴背景图的方式
  79.     QString qss;
  80.     QString qssCurrent;

  81.     if (bannerStyle == BannerStyle_Min) {
  82.         qss = "QLabel{background:#4380A8;}";
  83.         qssCurrent = "QLabel{background:#084279;}";
  84.     } else if (bannerStyle == BannerStyle_Num) {
  85.         qss = "QLabel{color:#FFFFFF;background:rgba(0,0,0,40);}";
  86.         qssCurrent = "QLabel{color:#FFFFFF;background:#0C7FC8;}";
  87.     }

  88.     //将当前广告指示器突出显示
  89.     foreach (QLabel *currentLab, labs) {
  90.         if (currentLab == lab) {
  91.             currentLab->setStyleSheet(qssCurrent);
  92.         } else {
  93.             currentLab->setStyleSheet(qss);
  94.         }
  95.     }

  96.     //更新索引和图片
  97.     currentIndex = labs.indexOf(lab);
  98.     widgetBg->setStyleSheet(QString("QWidget#widgetBg{border-image:url(%1);}").arg(names.at(currentIndex)));
  99. }

  100. int AdsWidget::getInterval() const
  101. {
  102.     return this->interval;
  103. }

  104. QSize AdsWidget::getBannerFixedSize() const
  105. {
  106.     return this->bannerFixedSize;
  107. }

  108. AdsWidget::BannerStyle AdsWidget::getBannerStyle() const
  109. {
  110.     return this->bannerStyle;
  111. }

  112. QString AdsWidget::getImageNames() const
  113. {
  114.     return this->imageNames;
  115. }

  116. QSize AdsWidget::sizeHint() const
  117. {
  118.     return QSize(200, 150);
  119. }

  120. QSize AdsWidget::minimumSizeHint() const
  121. {
  122.     return QSize(20, 15);
  123. }

  124. void AdsWidget::setInterval(int interval)
  125. {
  126.     if (this->interval != interval) {
  127.         this->interval = interval;
  128.         timer->setInterval(interval);
  129.     }
  130. }

  131. void AdsWidget::setBannerFixedSize(const QSize &bannerFixedSize)
  132. {
  133.     if (this->bannerFixedSize != bannerFixedSize) {
  134.         this->bannerFixedSize = bannerFixedSize;
  135.         foreach (QLabel *lab, labs) {
  136.             lab->setFixedSize(bannerFixedSize);
  137.         }
  138.     }
  139. }

  140. void AdsWidget::setBannerStyle(const AdsWidget::BannerStyle &bannerStyle)
  141. {
  142.     if (this->bannerStyle != bannerStyle) {
  143.         this->bannerStyle = bannerStyle;

  144.         foreach (QLabel *lab, labs) {
  145.             if (bannerStyle == BannerStyle_Min) {
  146.                 lab->setText("");
  147.             } else if (bannerStyle == BannerStyle_Num) {
  148.                 lab->setText(lab->text());
  149.             }
  150.         }
  151.     }
  152. }

  153. void AdsWidget::setImageNames(const QString &imageNames)
  154. {
  155.     if (this->imageNames != imageNames) {
  156.         this->imageNames = imageNames;

  157.         //先清空原有所有指示器
  158.         qDeleteAll(labs);
  159.         labs.clear();

  160.         //根据图片链表自动生成导航指示器和图片链表
  161.         names = this->imageNames.split(";");
  162.         for (int i = 0; i < names.count(); i++) {
  163.             QLabel *lab = new QLabel;
  164.             widgetBanner->layout()->addWidget(lab);
  165.             lab->setFixedSize(bannerFixedSize);
  166.             lab->setAlignment(Qt::AlignCenter);
  167.             lab->installEventFilter(this);
  168.             if (bannerStyle == BannerStyle_Num) {
  169.                 lab->setText(QString::number(i + 1));
  170.             }

  171.             labs.append(lab);
  172.         }

  173.         //立即显示第一张
  174.         changedAds();
  175.     }
  176. }

复制代码


六、控件介绍
1. 超过146个精美控件,涵盖了各种仪表盘、进度条、进度球、指南针、曲线图、标尺、温度计、导航条、导航栏,flatui、高亮按钮、滑动选择器、农历等。远超qwt集成的控件数量。
2. 每个类都可以独立成一个单独的控件,零耦合,每个控件一个头文件和一个实现文件,不依赖其他文件,方便单个控件以源码形式集成到项目中,较少代码量。qwt的控件类环环相扣,高度耦合,想要使用其中一个控件,必须包含所有的代码。
3. 全部纯Qt编写,QWidget+QPainter绘制,支持Qt4.6到Qt5.12的任何Qt版本,支持mingw、msvc、gcc等编译器,不乱码,可直接集成到Qt  Creator中,和自带的控件一样使用,大部分效果只要设置几个属性即可,极为方便。
4. 每个控件都有一个对应的单独的包含该控件源码的DEMO,方便参考使用。同时还提供一个所有控件使用的集成的DEMO。
5. 每个控件的源代码都有详细中文注释,都按照统一设计规范编写,方便学习自定义控件的编写。
6. 每个控件默认配色和demo对应的配色都非常精美。
7. 超过130个可见控件,6个不可见控件。
8. 部分控件提供多种样式风格选择,多种指示器样式选择。
9. 所有控件自适应窗体拉伸变化。
10.  集成自定义控件属性设计器,支持拖曳设计,所见即所得,支持导入导出xml格式。
11. 自带activex控件demo,所有控件可以直接运行在ie浏览器中。
12. 集成fontawesome图形字体+阿里巴巴iconfont收藏的几百个图形字体,享受图形字体带来的乐趣。
13. 所有控件最后生成一个dll动态库文件,可以直接集成到qtcreator中拖曳设计使用。

七、SDK下载
- SDK下载链接:https://pan.baidu.com/s/1tD9v1YPfE2fgYoK6lqUr1Q 提取码:lyhk
- 自定义控件+属性设计器欣赏:https://pan.baidu.com/s/1l6L3rKSiLu_uYi7lnL3ibQ 提取码:tmvl
- 下载链接中包含了各个版本的动态库文件,所有控件的头文件,使用demo。
- 自定义控件插件开放动态库dll使用(永久免费),无任何后门和限制,请放心使用。
- 目前已提供26个版本的dll,其中包括了qt5.12.3 msvc2017 32+64 mingw 32+64 的。
- 不定期增加控件和完善控件,不定期更新SDK,欢迎各位提出建议,谢谢!
- widget版本(QQ:517216493)qml版本(QQ:373955953)三峰驼(QQ:278969898)。
- 涛哥的知乎专栏 Qt进阶之路 https://zhuanlan.zhihu.com/TaoQt
- 欢迎关注微信公众号【高效程序员】,C++/Python、学习方法、写作技巧、热门技术、职场发展等内容,干货多多,福利多多!



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有帐号?立即注册

x
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册