这篇文章主要讲解了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_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);
}
看完上述内容,是不是对Qt转动轮播图的实现方法有进一步的了解,如果还想学习更多内容,欢迎关注亿速云行业资讯频道。
亿速云「云服务器」,即开即用、新一代英特尔至强铂金CPU、三副本存储NVMe SSD云盘,价格低至29元/月。点击查看>>
免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。