一、前言

广告轮播这个控件做的比较早,是很早以前定制一个电信客户端时候用到的,该客户端需要在首页展示轮播预先设定好的图片,图片的路径可以自由设定,然后轮播的间隔速度可以自由控制,同时该控件还需要提供两种指示器的风格,一种是迷你型的样式,一种是数字型的样式。

本控件很早就做好了,由于当时的QPainter功力不足,还不是很熟悉QPainter,采用的是效率比较低的直接用现有控件堆积而成,比如指示器采用的QLabel,用样式表来控制对应的形状,指示器所在的底部放一个widget,采用左右布局,然后右侧放一个弹簧把指示器label全部顶在左边,至于图片的显示,采用的是样式表中的border-image来设置,开个定时器,到了时间则设置成不同的border-image即可。这种方法虽然效率低了点,但是初学者很容易理解接收,甚至可以做出更多的效果,只要项目对CPU要求不高,也不失为一种还行的办法。

二、实现的功能

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

三、效果图





四、头文件代码

#ifndef ADSWIDGET_H
#define ADSWIDGET_H /**
* 广告轮播控件 作者:feiyangqingyun(QQ:517216493) 2016-12-22
* 1:可设置显示的图像
* 2:可添加多个广告
* 3:可设置指示器样式 迷你型样式 数字型样式
* 4:可设置指示器大小
* 5:可设置切换间隔
*/ #include <QWidget> class QLabel; #ifdef quc
#if (QT_VERSION < QT_VERSION_CHECK(5,7,0))
#include <QtDesigner/QDesignerExportWidget>
#else
#include <QtUiPlugin/QDesignerExportWidget>
#endif class QDESIGNER_WIDGET_EXPORT AdsWidget : public QWidget
#else
class AdsWidget : public QWidget
#endif {
Q_OBJECT
Q_ENUMS(BannerStyle) Q_PROPERTY(int interval READ getInterval WRITE setInterval)
Q_PROPERTY(QSize bannerFixedSize READ getBannerFixedSize WRITE setBannerFixedSize)
Q_PROPERTY(QString imageNames READ getImageNames WRITE setImageNames)
Q_PROPERTY(BannerStyle bannerStyle READ getBannerStyle WRITE setBannerStyle) public:
enum BannerStyle {
BannerStyle_Min = 0, //迷你型样式
BannerStyle_Num = 1 //数字型样式
}; explicit AdsWidget(QWidget *parent = 0);
~AdsWidget(); protected:
bool eventFilter(QObject *obj, QEvent *event); private:
int interval; //自动切换间隔
QSize bannerFixedSize; //导航指示器固定尺寸
BannerStyle bannerStyle; //导航指示器样式
QString imageNames; //导航图片集合字符串 int currentIndex; //当前显示的广告对应索引
QTimer *timer; //定时器轮播广告
QList<QLabel *> labs; //导航标签链表
QList<QString> names; //导航图片链表 QWidget *widgetBg; //存放广告图片的容器
QWidget *widgetBanner; //存放导航指示器的容器 private slots:
void initWidget();
void initForm();
void changedAds();
void changedAds(QLabel *lab); public:
int getInterval() const;
QSize getBannerFixedSize() const;
BannerStyle getBannerStyle() const;
QString getImageNames() const; QSize sizeHint() const;
QSize minimumSizeHint() const; public Q_SLOTS:
void setInterval(int interval);
void setBannerFixedSize(const QSize &bannerFixedSize);
void setBannerStyle(const BannerStyle &bannerStyle);
void setImageNames(const QString &imageNames);
}; #endif // ADSWIDGET_H

五、完整代码

#pragma execution_character_set("utf-8")

#include "adswidget.h"
#include "qevent.h"
#include "qlabel.h"
#include "qlayout.h"
#include "qtimer.h"
#include "qdebug.h" AdsWidget::AdsWidget(QWidget *parent) : QWidget(parent)
{
this->initWidget();
this->initForm();
} AdsWidget::~AdsWidget()
{
if (timer->isActive()) {
timer->stop();
}
} bool AdsWidget::eventFilter(QObject *obj, QEvent *event)
{
if (event->type() == QEvent::MouseButtonPress) {
if (obj->inherits("QLabel")) {
//先停止定时器,防止按下切换的时候短时间内再度切换
timer->stop();
changedAds((QLabel *)obj);
timer->start(interval);
}
} return QWidget::eventFilter(obj, event);
} void AdsWidget::initWidget()
{
QVBoxLayout *verticalLayout = new QVBoxLayout(this);
verticalLayout->setSpacing(0);
verticalLayout->setContentsMargins(0, 0, 0, 0); widgetBg = new QWidget(this);
widgetBg->setObjectName(QString::fromUtf8("widgetBg")); QGridLayout *gridLayout = new QGridLayout(widgetBg);
gridLayout->setSpacing(0);
gridLayout->setContentsMargins(0, 0, 0, 0); QSpacerItem *verticalSpacer = new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding);
gridLayout->addItem(verticalSpacer, 0, 0, 1, 1); widgetBanner = new QWidget(widgetBg);
widgetBanner->setObjectName(QString::fromUtf8("widgetBanner")); QHBoxLayout *horizontalLayout = new QHBoxLayout(widgetBanner);
horizontalLayout->setSpacing(3);
gridLayout->addWidget(widgetBanner, 1, 0, 1, 1); QSpacerItem *horizontalSpacer = new QSpacerItem(10, 10, QSizePolicy::Expanding, QSizePolicy::Minimum);
gridLayout->addItem(horizontalSpacer, 1, 1, 1, 1);
verticalLayout->addWidget(widgetBg);
} void AdsWidget::initForm()
{
interval = 3000;
bannerFixedSize = QSize(20, 20);
bannerStyle = BannerStyle_Num;
imageNames.clear(); currentIndex = 0;
timer = new QTimer(this);
timer->setInterval(interval);
connect(timer, SIGNAL(timeout()), this, SLOT(changedAds()));
timer->start();
} void AdsWidget::changedAds()
{
if (names.count() == 0) {
return;
} if (currentIndex < names.count() - 1) {
currentIndex++;
} else {
currentIndex = 0;
} changedAds(labs.at(currentIndex));
} void AdsWidget::changedAds(QLabel *lab)
{
//这里采用样式改变背景颜色的方式,也可以改成贴背景图的方式
QString qss;
QString qssCurrent; if (bannerStyle == BannerStyle_Min) {
qss = "QLabel{background:#4380A8;}";
qssCurrent = "QLabel{background:#084279;}";
} else if (bannerStyle == BannerStyle_Num) {
qss = "QLabel{color:#FFFFFF;background:rgba(0,0,0,40);}";
qssCurrent = "QLabel{color:#FFFFFF;background:#0C7FC8;}";
} //将当前广告指示器突出显示
foreach (QLabel *currentLab, labs) {
if (currentLab == lab) {
currentLab->setStyleSheet(qssCurrent);
} else {
currentLab->setStyleSheet(qss);
}
} //更新索引和图片
currentIndex = labs.indexOf(lab);
widgetBg->setStyleSheet(QString("QWidget#widgetBg{border-image:url(%1);}").arg(names.at(currentIndex)));
} int AdsWidget::getInterval() const
{
return this->interval;
} QSize AdsWidget::getBannerFixedSize() const
{
return this->bannerFixedSize;
} AdsWidget::BannerStyle AdsWidget::getBannerStyle() const
{
return this->bannerStyle;
} QString AdsWidget::getImageNames() const
{
return this->imageNames;
} QSize AdsWidget::sizeHint() const
{
return QSize(200, 150);
} QSize AdsWidget::minimumSizeHint() const
{
return QSize(20, 15);
} void AdsWidget::setInterval(int interval)
{
if (this->interval != interval) {
this->interval = interval;
timer->setInterval(interval);
}
} void AdsWidget::setBannerFixedSize(const QSize &bannerFixedSize)
{
if (this->bannerFixedSize != bannerFixedSize) {
this->bannerFixedSize = bannerFixedSize;
foreach (QLabel *lab, labs) {
lab->setFixedSize(bannerFixedSize);
}
}
} void AdsWidget::setBannerStyle(const AdsWidget::BannerStyle &bannerStyle)
{
if (this->bannerStyle != bannerStyle) {
this->bannerStyle = bannerStyle; foreach (QLabel *lab, labs) {
if (bannerStyle == BannerStyle_Min) {
lab->setText("");
} else if (bannerStyle == BannerStyle_Num) {
lab->setText(lab->text());
}
}
}
} void AdsWidget::setImageNames(const QString &imageNames)
{
if (this->imageNames != imageNames) {
this->imageNames = imageNames; //先清空原有所有指示器
qDeleteAll(labs);
labs.clear(); //根据图片链表自动生成导航指示器和图片链表
names = this->imageNames.split(";");
for (int i = 0; i < names.count(); i++) {
QLabel *lab = new QLabel;
widgetBanner->layout()->addWidget(lab);
lab->setFixedSize(bannerFixedSize);
lab->setAlignment(Qt::AlignCenter);
lab->installEventFilter(this);
if (bannerStyle == BannerStyle_Num) {
lab->setText(QString::number(i + 1));
} labs.append(lab);
} //立即显示第一张
changedAds();
}
}

六、控件介绍

  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、学习方法、写作技巧、热门技术、职场发展等内容,干货多多,福利多多!

Qt编写自定义控件23-广告轮播控件的更多相关文章

  1. Qt编写自定义控件24-图片轮播控件

    一.前言 上一篇文章写的广告轮播控件,采用的传统widget堆积设置样式表做的,这次必须要用到更高级的QPainter来绘制了,这个才是最高效的办法,本控件参考雨田哥的轮播控件,经过大规模的改造而成, ...

  2. 第四十六篇、UICollectionView广告轮播控件

    这是利用人的视觉错觉来实现无限轮播,UICollectionView 有很好的重用机制,这只是部分核心代码,后期还要继续完善和代码重构. #import <UIKit/UIKit.h> # ...

  3. Qt编写自定义控件11-设备防区按钮控件

    前言 在很多项目应用中,需要根据数据动态生成对象显示在地图上,比如地图标注,同时还需要可拖动对象到指定位置显示,能有多种状态指示,安防领域一般用来表示防区或者设备,可以直接显示防区号,有多种状态颜色指 ...

  4. Qt编写自定义控件8-动画按钮组控件

    前言 动画按钮组控件可以用来当做各种漂亮的导航条用,既可以设置成顶部底部+左侧右侧,还自带精美的滑动效果,还可以设置悬停滑动等各种颜色,原创作者雨田哥(QQ:3246214072),驰骋Qt控件界多年 ...

  5. Qt编写自定义控件32-等待进度条控件

    一.前言 在各种各样的执行任务界面,有时候需要比较多的时间,需要给出一个直观的等待进度条表示当前正在执行的进度,而不至于懵逼在那里,用户不会觉得程序死了还是干嘛了. 等待进度条有好几种办法,比如直接叫 ...

  6. Android之仿京东淘宝的自动无限轮播控件

    在App的开发中,很多的时候都需要实现类似京东淘宝一样的自动无限轮播的广告栏,所以就自己写了一个,下面是我自定义控件的思路和过程. 一.自定义控件属性 新建自定义控件SliderLayout继承于Re ...

  7. Android图片轮播控件

    Android广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间.位置.图片加载框架等! 使用步骤 Step 1.依赖banner Gradle dependenci ...

  8. Android-----------广告图片轮播控件

    Banner广告图片轮播控件,支持无限循环和多种主题,可以灵活设置轮播样式.动画.轮播和切换时间.位置.图片加载框架等! 很多Android APP中都有广告栏,我也用过很多次了,特来写一篇博文. 先 ...

  9. Android 开发最牛的图片轮播控件,基本什么都包含了。

    Android图片轮播控件  源码下载地址: Android 图片轮播 现在的绝大数app都有banner界面,实现循环播放多个广告图片和手动滑动循环等功能.因为ViewPager并不支持循环翻页, ...

随机推荐

  1. markdown编辑器抉择经历(做笔记\多系统用户)

    之前一段时间,为了找到一款合适的md编辑器可谓是费尽了心思,用了我不少时间才找到一款合适的跨平台的又美观方便的编辑器----马克飞象. 感觉虽然有些编辑器功能很强大,对于使用性单一的用户,比如像我这种 ...

  2. 15_sqoop数据导出

    1.Sqoop的数据导出 将数据从HDFS导出到RDBMS数据库,导出前,目标表必须存在于目标数据库中 默认操作是将文件中的数据使用INSERT语句插入到表中 更新模式下,是生成UPDATE语句更新表 ...

  3. Java数组直接选择排序、sort()排序

    /** * 1.数组sort()排序 * 2.直接选择排序(两重for循环排序) */ import java.lang.*; import java.lang.reflect.Array; impo ...

  4. 原生JS实现简单富文本编辑器

    <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...

  5. Web UI开发速速种草—Kendo UI for jQuery网格编辑操作概述

    Kendo UI for jQuery最新试用版下载 Kendo UI目前最新提供Kendo UI for jQuery.Kendo UI for Angular.Kendo UI Support f ...

  6. 你的VCL界面开发不知所措?这款工具绝对超出预料

    DevExpress VCL Controls是 Devexpress公司旗下最老牌的用户界面套包.所包含的控件有:数据录入,图表,数据分析,导航,布局,网格,日程管理,样式,打印和工作流等,让您快速 ...

  7. K3CLOUD 常用数据表

    二.K3 Cloud 开发插件<K3 Cloud 常用数据表整理>一.数据库查询常用表 按 Ctrl+C 复制代码 按 Ctrl+C 复制代码 通过表T_META_OBJECTTYPE的F ...

  8. BZOJ 2281: [Sdoi2011]黑白棋 (Nim游戏+dp计数)

    题意 这题目有一点问题,应该是在n个格子里有k个棋子,k是偶数.从左到右一白一黑间隔出现.有两个人不妨叫做小白和小黑.两个人轮流操作,每个人可以选 1~d 枚自己颜色的棋子,如果是白色则只能向右移动, ...

  9. [Google Guava] 11-事件总线

    原文链接 译文连接 译者:沈义扬 传统上,Java的进程内事件分发都是通过发布者和订阅者之间的显式注册实现的.设计EventBus就是为了取代这种显示注册方式,使组件间有了更好的解耦.EventBus ...

  10. springboot2.0入门(九)-- springboot使用mybatis-generator自动代码生成

    一.配置文件引入 插件引入,引入 <plugin> <groupId>org.mybatis.generator</groupId> <artifactId& ...