Qt转动轮播图的实现

mac2022-06-30  94

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_OBJECT public: 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_OBJECT public: 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_OBJECT public: 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_OBJECT public: 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); }

完整工程代码下载

最新回复(0)