Qt转动轮播图的实现方法
这篇文章主要讲解了Qt转动轮播图的实现方法,内容清晰明了,对此有兴趣的小伙伴可以学习一下,相信大家阅读完之后会有帮助。
Qt轮播图的实现代码,供大家参考,具体内容如下
qt轮播图简单的实现,功能会在后面完善
效果图:
这里我是用了QGraphicsScene+QGraphicsView+QGraphicsObject,其中对QGraphicsView和QGraphicsObject进行继承派生类功能进行了添加。时间有限,直接贴上关键代码部分供大家参考。
//pictrueitem.h#ifndef PICTRUEITEM_H#define PICTRUEITEM_H#include <QGraphicsPixmapItem>#include <QGraphicsItem>#include <QGraphicsObject>#include <QPixmap>class PictrueItem : public QGraphicsObject{ Q_OBJECTpublic: explicit PictrueItem(QGraphicsItem *parent = Q_NULLPTR); explicit PictrueItem(const QPixmap &pixmap, QGraphicsItem *parent = Q_NULLPTR); virtual ~PictrueItem(); void setPixmap(const QPixmap &pixmap); QPixmap pixmap() const; virtual QRectF boundingRect() const; void setTransformationMode(Qt::TransformationMode mode); QPointF offset() const; void setOffset(const QPointF &offset); virtual int type()const; void setType(int type); int itemId()const; void setItemId(int id);protected: void mousePressEvent(QGraphicsSceneMouseEvent *event); void mouseReleaseEvent(QGraphicsSceneMouseEvent *event); virtual void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget);Q_SIGNALS: void clicked(); void clickedId(int);private: QPointF pressedScenePoint; QPointF m_offset; QPointF m_pos; Qt::TransformationMode mode; QPixmap m_pixmap; bool isPressed; int m_type; int m_id; qreal m_pointPercent;};#endif // PICTRUEITEM_H
//pictrueitem.cpp#include "pictrueitem.h"#include <QGraphicsSceneMouseEvent>#include <QPainter>#include <QDebug>PictrueItem::PictrueItem(QGraphicsItem *parent) :QGraphicsObject(parent), isPressed(false), mode(Qt::SmoothTransformation), m_type(0), m_id(0), m_pointPercent((qreal)0.0){}PictrueItem::PictrueItem(const QPixmap &pixmap, QGraphicsItem *parent) :QGraphicsObject(parent), isPressed(false), mode(Qt::SmoothTransformation), m_type(0){ m_pixmap = pixmap;}PictrueItem::~PictrueItem(){}void PictrueItem::setPixmap(const QPixmap &pixmap){ prepareGeometryChange(); m_pixmap = pixmap; update();}QPixmap PictrueItem::pixmap() const{ return m_pixmap;}QRectF PictrueItem::boundingRect() const{ if(m_pixmap.isNull()) return QRectF(); return QRectF(m_offset, m_pixmap.size() / m_pixmap.devicePixelRatio());}void PictrueItem::setTransformationMode(Qt::TransformationMode mode){ if (mode != this->mode) { this->mode = mode; update(); }}QPointF PictrueItem::offset() const{ return m_offset;}void PictrueItem::setOffset(const QPointF &offset){ m_offset = offset; if (m_offset == offset) return; prepareGeometryChange(); m_offset = offset; update();}int PictrueItem::type() const{ return m_type;}void PictrueItem::setType(int type){ m_type = type;}int PictrueItem::itemId() const{ return m_id;}void PictrueItem::setItemId(int id){ m_id = id;}void PictrueItem::mousePressEvent(QGraphicsSceneMouseEvent *event){ //只响应鼠标左键 if(event->button() == Qt::LeftButton) { pressedScenePoint = event->pos(); isPressed = true; }}void PictrueItem::mouseReleaseEvent(QGraphicsSceneMouseEvent *event){ if(event->button() == Qt::LeftButton){ if(isPressed && boundingRect().contains(event->pos()) && boundingRect().contains(pressedScenePoint)) { isPressed = false; emit clicked(); emit clickedId(type()); } }}void PictrueItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget){ Q_UNUSED(widget); Q_UNUSED(option); painter->setRenderHint(QPainter::SmoothPixmapTransform, (this->mode == Qt::SmoothTransformation)); painter->drawPixmap(m_offset, m_pixmap);}
//pictrueview.h#ifndef PICTRUEVIEW_H#define PICTRUEVIEW_H#include <QGraphicsView>class PictrueView : public QGraphicsView{ Q_OBJECTpublic: PictrueView(QWidget *parent = Q_NULLPTR); virtual ~PictrueView();protected: void resizeEvent(QResizeEvent *event);public:Q_SIGNALS: void sizeChanged(const QSize &);};#endif // PICTRUEVIEW_H
//pictrueview.cpp#include "pictrueview.h"#include <QResizeEvent>PictrueView::PictrueView(QWidget *parent) :QGraphicsView(parent){}PictrueView::~PictrueView(){ //none}void PictrueView::resizeEvent(QResizeEvent *event){ emit sizeChanged(event->size()); return QGraphicsView::resizeEvent(event);}
下面那行按钮实现
//pictruebutton.h#ifndef PICTRUERADIOBUTTON_H#define PICTRUERADIOBUTTON_H#include <QAbstractButton>class PictrueButton : public QAbstractButton{ Q_OBJECTpublic: explicit PictrueButton(QWidget *parent = Q_NULLPTR); ~PictrueButton(); int id()const; void setId(int id);Q_SIGNALS: void entered(); void entered(int);protected: virtual void paintEvent(QPaintEvent *); virtual void enterEvent(QEvent *event); virtual void leaveEvent(QEvent *event);private: bool m_isSelected; int m_id;};#endif // PICTRUERADIOBUTTON_H
//pictruebutton.cpp#include "pictruebutton.h"#include <QPen>#include <QPainter>#include <QDebug>#include <QPainterPath>PictrueButton::PictrueButton(QWidget *parent) :QAbstractButton(parent), m_isSelected(false), m_id(0){ setCheckable(true); setFixedSize(50,10);}PictrueButton::~PictrueButton(){}int PictrueButton::id() const{ return m_id;}void PictrueButton::setId(int id){ m_id = id;}void PictrueButton::paintEvent(QPaintEvent *){ QPainter painter(this); QRectF drawRect = this->rect(); QPainterPath drawPath; qDebug()<<drawRect; QPen drawPen; drawPen.setWidth(3); //选中为蓝,未选中为灰 drawPen.setColor(Qt::gray); painter.setPen(drawPen); //抗锯齿 painter.setRenderHint(QPainter::Antialiasing); drawPath.addRoundedRect(drawRect,10,10); painter.setClipPath(drawPath); if(isChecked()) painter.fillRect(drawRect,QColor(0,0,255,128)); else painter.fillRect(drawRect,QColor(128,128,128,128));}void PictrueButton::enterEvent(QEvent *event){ if(!isChecked()) setChecked(true); emit entered(m_id); return QAbstractButton::enterEvent(event);}void PictrueButton::leaveEvent(QEvent *event){ return QAbstractButton::leaveEvent(event);}
//qmainWindow.h#ifndef MAINWINDOW_H#define MAINWINDOW_H#include <QMainWindow>#define RAW_VIEW_SIZE QSize(476,414)#define SCALE_VIEW_PIXMAP (qreal)2/1 //View与图片比例#define SCALE_BIG_SMALL (qreal)2/1 //图片大小比例//P1-P8,8个位置,根据需要改动#define P1 (qreal)0.00#define P2 (qreal)0.25#define P3 (qreal)0.50#define P4 (qreal)0.75#define P5 (qreal)1.00#define P6 P4#define P7 P3#define P8 P2#define MID_TYPE 2#define FPS 60//帧数,每秒#define DURATION_MS 500//移动一次图元经过时间,毫秒,不得低于帧数namespace Ui {class MainWindow;}class QGraphicsScene;class QButtonGroup;class MainWindow : public QMainWindow{ Q_OBJECTpublic: enum Rules:int{ RuleA = 1, RuleB = -1, RuleC = 2, RuleD = -2 }; explicit MainWindow(QWidget *parent = 0); ~MainWindow(); int getIndexByRules(int oldIndex,int rule); template<typename T> void rollList(QList<T> &oldList, int dir, int count); void rollItem(int rollDir,unsigned rollCount);public Q_SLOTS: void timerOutFunc(); void nextItem(); void previousItem(); void clickedItemRoll(int type);protected:private: Ui::MainWindow *ui; QTimer *m_timer; QGraphicsScene *m_scene; QLineF midLine; QList<qreal> pointList; QList<QPixmap> pixmapList; QList<qreal> zValueList; QList<qreal> pixmapScaleList; int m_index; Rules currentRule; unsigned m_rollCount; QButtonGroup *btnGroup; bool btnMoveEnable;};#endif // MAINWINDOW_H
下面是滚动的关键代码
void MainWindow::timerOutFunc(){ for(int i = 0; i<8; i++) { if(qAbs(midLine.pointAt(pointList[getIndexByRules(i,dir)]).x()-itemList[i]->pos().x())<qAbs(unitList[i])) { if(finishList.contains(i)) continue; itemList[i]->setPos(midLine.pointAt(pointList[getIndexByRules(i,dir)])); //设置新的显示优先级 itemList[i]->setScale(pixmapScaleList[getIndexByRules(i,dir)]); //设置新的类型 itemList[i]->setType(getIndexByRules(i,dir)); //i==7-->最后一个图元移动完成 finishList.append(i); if(finishList.size() == 8) { //循环旋转图元表和图片表 rollList(itemList,dir,1); rollList(pixmapList,dir,1); for(int i = 0; i<8; i++) itemList[i]->setZValue(zValueList[i]); m_timer->stop(); finishList.clear(); if(btnGroup->checkedId()!=itemList[MID_TYPE]->itemId()) btnGroup->button(getIndexByRules(btnGroup->checkedId(),dir))->setChecked(true); if(--m_rollCount) { if(dir == 1) nextItem(); else previousItem(); } break; } } else { //按计算好的移动单位移动一次 itemList[i]->setPos(QPointF(itemList[i]->pos().x()+unitList[i],itemList[i]->pos().y())); //转换因子不是1.0时进行转换设置 if(transScaleList[i] != (qreal)1.0) { itemList[i]->setScale(itemList[i]->scale()*transScaleList[i]); } } m_scene->invalidate(); }}
void MainWindow::rollItem(int rollDir, unsigned rollCount){ if(m_timer->isActive()) return; //清除之前的空间差列表和移动单位列表 m_rollCount = rollCount; spaceList.clear(); unitList.clear(); transScaleList.clear(); dir = rollDir; qDebug()<<"rollCount"<<rollCount; for(int i = 0; i<8; i++) { spaceList.append(midLine.pointAt(pointList[getIndexByRules(i,dir)]).x()-itemList[i]->pos().x());//计算移动总距离 unitList.append(spaceList[i]/(FPS*DURATION_MS/1000));//计算移动单个距离 transScaleList.append(pow(pixmapScaleList[getIndexByRules(i,dir)]/pixmapScaleList[i],\ (qreal)1/(FPS*DURATION_MS/1000)));//计算增长倍数 } //启动定时器 m_timer->start();}void MainWindow::nextItem(){ rollItem(1,1);}void MainWindow::previousItem(){ rollItem(-1,1);}
看完上述内容,是不是对Qt转动轮播图的实现方法有进一步的了解,如果还想学习更多内容,欢迎关注亿速云行业资讯频道。
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。