上一篇文章寫的廣告輪播控件,採用的傳統widget堆積設置樣式表作的,此次必需要用到更高級的QPainter來繪製了,這個纔是最高效的辦法,本控件參考雨田哥的輪播控件,通過大規模的改造而成,相比於原來的廣告輪播控件,本控件能夠說完爆他,按在地上使勁摩擦。除了能夠設置圖片路徑集合之外,還能夠設置對應的提示信息,這個在衆多的web輪播圖片效果中最多見,好比新聞的標題等,能夠更直觀的顯示當前圖片,並且單擊圖片還能夠支持跳轉,指示器的位置也能設置左邊+中間+右邊,指示器的樣式更加增長到橢圓條狀+圓形+矩形+小圓點+長條狀多種可選擇,能夠說涵蓋了各類web輪播圖片的效果,還能夠設置鼠標懸停暫停輪播,以便看清說明後鼠標移開繼續輪播。指示器的寬高顏色等,都是能夠自由設定的,這個對於採用QPainter繪製來講,是最好自定義的,無非就是設置對應的畫筆QPen和對應的畫布QBrush的顏色啦。linux
#ifndef ADSWIDGET2_H #define ADSWIDGET2_H /** * 廣告輪播控件2 做者:feiyangqingyun(QQ:517216493) 2018-9-12 * 參考雨田哥(QQ:3246214072) https://blog.csdn.net/ly305750665/article/details/82496046 * 1:可設置圖片路徑集合 * 2:可設置提示信息集合 * 3:可設置指示器最小寬度和最大寬度 * 4:可設置圖片切換間隔 * 5:可設置指示器顏色和提示文字顏色 * 6:可設置指示器高度 * 7:可設置指示器顯示序號 * 8:可設置指示器位置 左邊+中間+右邊 * 9:可設置指示器的樣式 橢圓條狀+圓形+矩形+小圓點+長條狀 * 10:可設置鼠標懸停中止輪播 */ #include <QWidget> class QLabel; class QHBoxLayout; class QSpacerItem; class QParallelAnimationGroup; class QPropertyAnimation; #ifdef quc #if (QT_VERSION < QT_VERSION_CHECK(5,7,0)) #include <QtDesigner/QDesignerExportWidget> #else #include <QtUiPlugin/QDesignerExportWidget> #endif class QDESIGNER_WIDGET_EXPORT AdsWidget2 : public QWidget #else class AdsWidget2 : public QWidget #endif { Q_OBJECT Q_ENUMS(NavPosition) Q_ENUMS(NavStyle) Q_PROPERTY(bool hoverStop READ getHoverStop WRITE setHoverStop) Q_PROPERTY(bool showNumber READ getShowNumber WRITE setShowNumber) Q_PROPERTY(int minHeight READ getMinHeight WRITE setMinHeight) Q_PROPERTY(int minWidth READ getMinWidth WRITE setMinWidth) Q_PROPERTY(int maxWidth READ getMaxWidth WRITE setMaxWidth) Q_PROPERTY(int interval READ getInterval WRITE setInterval) Q_PROPERTY(int navRadius READ getNavRadius WRITE setNavRadius) Q_PROPERTY(QColor navColor READ getNavColor WRITE setNavColor) Q_PROPERTY(QColor textColor READ getTextColor WRITE setTextColor) Q_PROPERTY(QColor tipColor READ getTipColor WRITE setTipColor) Q_PROPERTY(QColor darkColor READ getDarkColor WRITE setDarkColor) Q_PROPERTY(QString imageNames READ getImageNames WRITE setImageNames) Q_PROPERTY(QString imageTips READ getImageTips WRITE setImageTips) Q_PROPERTY(NavPosition navPosition READ getNavPosition WRITE setNavPosition) Q_PROPERTY(NavStyle navStyle READ getNavStyle WRITE setNavStyle) public: enum NavPosition { NavPosition_Left = 0, //左邊位置 NavPosition_Center = 1, //中間位置 NavPosition_Right = 2 //右側位置 }; enum NavStyle { NavStyle_Ellipse = 0, //橢圓條狀 NavStyle_Circle = 1, //圓形 NavStyle_Rect = 2, //矩形 NavStyle_Dot = 3, //小圓點 NavStyle_LongRect = 4 //長條狀 }; AdsWidget2(QWidget *parent = 0); ~AdsWidget2(); protected: bool eventFilter(QObject *obj, QEvent *event); void enterEvent(QEvent *); void leaveEvent(QEvent *); void showEvent(QShowEvent *); void paintEvent(QPaintEvent *); private: bool hoverStop; //鼠標懸停中止輪播 bool showNumber; //是否顯示序號 int minHeight; //指示器最小高度 int minWidth; //指示器最小拉伸寬度 int maxWidth; //指示器最大拉伸寬度 int interval; //圖片切換間隔,單位毫秒 int navRadius; //指示器圓角角度 QColor navColor; //指示器顏色 QColor textColor; //指示器文字顏色 QColor tipColor; //提示文字顏色 QColor darkColor; //當前指示器加深顏色 QString imageNames; //圖片名稱 QString imageTips; //提示信息 NavPosition navPosition;//指示器位置 NavStyle navStyle; //指示器樣式 QList<QString> names; //圖片名稱集合 QList<QString> tips; //提示信息集合 QList<QLabel *> labs; //存儲指示器集合 bool leftToRight; //從左往右切換 int offset; //圖片切換偏移量 int currentIndex; //當前圖片索引 int previousIndex; //上一張圖片索引 QString qssNormal; //正常狀態樣式 QString qssCurrent; //當前狀態樣式 QTimer *timer; //定時器切換 QHBoxLayout *layout; //指示器所在佈局 QSpacerItem *spacerLeft;//左側彈簧 QSpacerItem *spacerRight;//右側彈簧 QWidget *widgetNav; //存放導航指示器的容器 //動畫切換 QParallelAnimationGroup *animationGroup; QPropertyAnimation *animationImage; QPropertyAnimation *animationMin; QPropertyAnimation *animationMax; private slots: void initWidget(); void initForm(); void initQss(); void changedAds(); void changedAds(QLabel *lab); void changedImage(const QVariant &); void changedMin(const QVariant &); void changedMax(const QVariant &); public: bool getHoverStop() const; bool getShowNumber() const; int getMinHeight() const; int getMinWidth() const; int getMaxWidth() const; int getInterval() const; int getNavRadius() const; QColor getNavColor() const; QColor getTextColor() const; QColor getTipColor() const; QColor getDarkColor() const; QString getImageNames() const; QString getImageTips() const; NavPosition getNavPosition()const; NavStyle getNavStyle() const; QSize sizeHint() const; QSize minimumSizeHint() const; public Q_SLOTS: //設置鼠標懸停中止輪播 void setHoverStop(bool hoverStop); //設置是否顯示序號 void setShowNumber(bool showNumber); //設置指示器高度 void setMinHeight(int minHeight); //設置最小拉伸寬度 void setMinWidth(int minWidth); //設置最大拉伸寬度 void setMaxWidth(int maxWidth); //設置切換間隔 void setInterval(int interval); //設置指示器圓角角度 void setNavRadius(int navRadius); //設置指示器顏色 void setNavColor(const QColor &navColor); //設置指示器文字顏色 void setTextColor(const QColor &textColor); //設置提示信息顏色 void setTipColor(const QColor &tipColor); //設置加深顏色 void setDarkColor(const QColor &darkColor); //設置圖片名稱 void setImageNames(const QString &imageNames); //設置提示信息 void setImageTips(const QString &imageTips); //設置指示器位置 void setNavPosition(const NavPosition &navPosition); //設置指示器樣式 void setNavStyle(const NavStyle &navStyle); }; #endif // ADSWIDGET2_H
void AdsWidget2::paintEvent(QPaintEvent *) { if (names.count() == 0) { return; } int width = this->width(); int height = this->height(); QPainter painter(this); painter.setRenderHints(QPainter::SmoothPixmapTransform | QPainter::TextAntialiasing); QTextOption option(Qt::AlignLeft | Qt::AlignVCenter); painter.setPen(tipColor); //設置字體 QFont font; font.setPixelSize(15); painter.setFont(font); //取出上一張圖片+當前圖片,並平滑縮放 QPixmap previousPix(names.at(previousIndex)); QPixmap currentPix(names.at(currentIndex)); previousPix = previousPix.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); currentPix = currentPix.scaled(width, height, Qt::KeepAspectRatioByExpanding, Qt::SmoothTransformation); int widthOffset = offset + width; if (leftToRight) { widthOffset = offset - width; } //繪製上一張圖片 painter.drawPixmap(offset, 0, previousPix); //繪製當前圖片 painter.drawPixmap(widthOffset, 0, currentPix); //繪製上一張圖片提示信息,有可能上一張圖片提示信息爲空 if (previousIndex <= tips.count() - 1) { painter.drawText(QRect(offset + 10, height - minHeight - 40, width - 20, 30), tips.at(previousIndex), option); } //繪製當前圖片提示信息,有可能當前圖片提示信息爲空 if (currentIndex <= tips.count() - 1) { painter.drawText(QRect(widthOffset + 10, height - minHeight - 40, width - 20, 30), tips.at(currentIndex), option); } } void AdsWidget2::initWidget() { //放置指示器的窗體載體 widgetNav = new QWidget(this); widgetNav->setObjectName(QString::fromUtf8("widgetNav")); //給指示器窗體加上左右佈局 layout = new QHBoxLayout(widgetNav); layout->setSpacing(3); //主佈局,上下佈局 QVBoxLayout *verticalLayout = new QVBoxLayout(this); verticalLayout->setSpacing(0); verticalLayout->setContentsMargins(0, 0, 0, 0); //上部彈簧,用於將指示器區域彈到底部 QSpacerItem *verticalSpacer = new QSpacerItem(10, 10, QSizePolicy::Minimum, QSizePolicy::Expanding); verticalLayout->addItem(verticalSpacer); //將指示器窗體加入到主佈局中下部 verticalLayout->addWidget(widgetNav); //實例化左側右側彈簧 spacerLeft = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum); spacerRight = new QSpacerItem(1, 1, QSizePolicy::Expanding, QSizePolicy::Minimum); } void AdsWidget2::initForm() { hoverStop = true; showNumber = false; minHeight = 6; minWidth = 6; maxWidth = 25; interval = 3000; navRadius = 3; navColor = QColor(220, 220, 220); textColor = QColor(20, 20, 20); tipColor = QColor(255, 255, 255); darkColor = QColor(255, 255, 255); imageNames.clear(); imageTips.clear(); navPosition = NavPosition_Left; navStyle = NavStyle_Ellipse; leftToRight = true; offset = 0; currentIndex = 0; previousIndex = 0; //定時器切換圖片 timer = new QTimer(this); timer->setInterval(interval); connect(timer, SIGNAL(timeout()), this, SLOT(changedAds())); this->setMouseTracking(true); //定義動畫組 animationGroup = new QParallelAnimationGroup(this); //定義動畫切換圖片 animationImage = new QPropertyAnimation(this, ""); connect(animationImage, SIGNAL(valueChanged(const QVariant &)), this, SLOT(changedImage(const QVariant &))); animationImage->setEasingCurve(QEasingCurve::OutCirc); animationImage->setDuration(1000); animationGroup->addAnimation(animationImage); QSequentialAnimationGroup *sequentialGroup = new QSequentialAnimationGroup(animationGroup); //用於切換最小拉伸寬度 animationMin = new QPropertyAnimation(sequentialGroup, ""); connect(animationMin, SIGNAL(valueChanged(const QVariant &)), this, SLOT(changedMin(const QVariant &))); animationMin->setEasingCurve(QEasingCurve::OutCubic); animationMin->setDuration(500); //用於切換最大拉伸寬度 animationMax = new QPropertyAnimation(sequentialGroup, ""); connect(animationMax, SIGNAL(valueChanged(const QVariant &)), this, SLOT(changedMax(const QVariant &))); animationMax->setEasingCurve(QEasingCurve::OutCubic); animationMax->setDuration(500); //按鈕切換串行運行 sequentialGroup->addAnimation(animationMin); sequentialGroup->addAnimation(animationMax); animationGroup->addAnimation(sequentialGroup); } void AdsWidget2::initQss() { //可自行拓展自定義樣式 if (navStyle == NavStyle_Dot) { qssNormal = QString("border:none;background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5," "stop:0 #00FFFFFF,stop:0.4 #00FFFFFF," "stop:0.5 #00FFFFFF,stop:0.6 #00FFFFFF,stop:0.7 rgba(%1,%2,%3,%4));" "color:rgba(%5,%6,%7,%8);border-radius:%9px;") .arg(navColor.red()).arg(navColor.green()).arg(navColor.blue()).arg(navColor.alpha()) .arg(textColor.red()).arg(textColor.green()).arg(textColor.blue()).arg(navColor.alpha()).arg(navRadius); qssCurrent = QString("border:none;background:qradialgradient(spread:pad,cx:0.5,cy:0.5,radius:0.5,fx:0.5,fy:0.5," "stop:0 rgba(%1,%2,%3,%4),stop:0.4 rgba(%1,%2,%3,%4)," "stop:0.5 #00FFFFFF,stop:0.6 #00FFFFFF,stop:0.7 rgba(%1,%2,%3,%4));" "color:rgba(%5,%6,%7,%8);border-radius:%9px;") .arg(darkColor.red()).arg(darkColor.green()).arg(darkColor.blue()).arg(darkColor.alpha()) .arg(textColor.red()).arg(textColor.green()).arg(textColor.blue()).arg(navColor.alpha()).arg(navRadius); } else { qssNormal = QString("border:none;background:rgba(%1,%2,%3,%4);color:rgba(%5,%6,%7,%8);border-radius:%9px;") .arg(navColor.red()).arg(navColor.green()).arg(navColor.blue()).arg(navColor.alpha()) .arg(textColor.red()).arg(textColor.green()).arg(textColor.blue()).arg(navColor.alpha()).arg(navRadius); qssCurrent = QString("border:none;background:rgba(%1,%2,%3,%4);color:rgba(%5,%6,%7,%8);border-radius:%9px;") .arg(darkColor.red()).arg(darkColor.green()).arg(darkColor.blue()).arg(darkColor.alpha()) .arg(textColor.red()).arg(textColor.green()).arg(textColor.blue()).arg(textColor.alpha()).arg(navRadius); } } void AdsWidget2::changedAds() { if (names.count() == 0) { return; } previousIndex = currentIndex; if (currentIndex < names.count() - 1) { currentIndex++; } else { currentIndex = 0; } changedAds(labs.at(currentIndex)); }