一、简介
最近有一个Qt效果需求:类似于图片轮播的效果,但是其中的图标可以被鼠标点击/手指触摸,从而进行相对应的逻辑处理。于是乎小生使用Qt进行了实现,本文给出一个实现思路和一个实现过程中大致的效果。
效果走一波
二、核心思路
(1)使用Qt的图形视图框架来完成。使用这一点比较方便也较为容易实现。
(2)使用QGraphicsEffect
来对图形框架中的图形项进行模糊。
(2)使用QPropertyAnimation
属性动画来进行场景中图形项的动画操作。
三、核心代码
(3-1)【模糊效果类:BlurEffect】
#include "blureffect.h"
BlurEffect::BlurEffect(QGraphicsItem *item)
: QGraphicsBlurEffect()
, m_baseLine(200), item(item)
{
}
void BlurEffect::adjustForItem()
{
qreal y = m_baseLine - item->pos().y();
qreal radius = qBound(qreal(0.0), y / 32, qreal(16.0));
setBlurRadius(radius);
}
QRectF BlurEffect::boundingRect() const
{
const_cast<BlurEffect *>(this)->adjustForItem();
return QGraphicsBlurEffect::boundingRect();
}
void BlurEffect::draw(QPainter *painter)
{
adjustForItem();
QGraphicsBlurEffect::draw(painter);
}
(3-2)【图形视图类:FuzzyRotate】
#include "blurpicker.h"
#include <QtWidgets>
#include <QtCore/qmath.h>
#include <qmath.h>
#include "blureffect.h"
FuzzyRotate::FuzzyRotate(QWidget *parent): QGraphicsView(parent),
m_index(0.0),
m_animation(this,"index")
{
setScene(new QGraphicsScene(this));
this->setWindowTitle(QString("iriczhao | demos"));
setupScene();
setIndex(0);
m_animation.setDuration(400);
m_animation.setEasingCurve(QEasingCurve::InOutSine);
setRenderHint(QPainter::Antialiasing, true);
setFrameStyle(QFrame::NoFrame);
m_timer = new QTimer(this);
connect(m_timer,&QTimer::timeout,this,&FuzzyRotate::rotateHandle);
m_timer->start(1500);
}
void FuzzyRotate::rotateHandle()
{
m_animation.setEndValue(m_index + 1);
m_animation.start();
}
qreal FuzzyRotate::index() const
{
return m_index;
}
void FuzzyRotate::setIndex(qreal index)
{
m_index = index;
qreal baseline = 420;
const qreal iconAngle = 2 * M_PI / m_icons.count();
for (int i = 0; i < m_icons.count(); ++i) {
QGraphicsItem *icon = m_icons[i];
qreal a = (i + m_index) * iconAngle;
qreal xs = 300 * qSin(a);
qreal ys = 120 * qCos(a);
QPointF pos(xs, ys);
pos += QPointF(390, 260);
icon->setPos(pos);
baseline = qMax(baseline, ys);
static_cast<BlurEffect *>(icon->graphicsEffect())->setBaseLine(baseline);
}
scene()->update();
}
void FuzzyRotate::setupScene()
{
scene()->setSceneRect(0, 0, 910, 627);
QStringList names;
names << ":/images/accessories-calculator.png";
names << ":/images/accessories-text-editor.png";
names << ":/images/help-browser.png";
names << ":/images/internet-group-chat.png";
names << ":/images/internet-mail.png";
names << ":/images/internet-web-browser.png";
names << ":/images/office-calendar.png";
names << ":/images/system-users.png";
QGraphicsPixmapItem *bg = scene()->addPixmap(QPixmap(":/images/background1.png"));
bg->setZValue(-270);
for (int i = 0; i < names.count(); i++) {
QPixmap pixmap(names[i]);
QPushButton *iconBtn = new QPushButton();
iconBtn->setIcon(pixmap);
iconBtn->setIconSize(pixmap.size());
iconBtn->resize(pixmap.size());
iconBtn->setMask(pixmap.mask());
iconBtn->setStyleSheet("border:0px;");
iconBtn->setObjectName(QString("%1").arg(i));
connect(iconBtn,&QPushButton::clicked,this,&FuzzyRotate::btnClickedHandler);
QGraphicsWidget *btn = scene()->addWidget(iconBtn);
btn->setZValue(360);
btn->setGraphicsEffect(new BlurEffect(btn));
m_icons << btn;
}
}
void FuzzyRotate::btnClickedHandler()
{
QObject *name = sender();
QMessageBox msg(this);
msg.setText(QString("[%1]icon clicked----------------").arg(name->objectName()));
msg.exec();
}
void FuzzyRotate::enterEvent(QEvent *e)
{
Q_UNUSED(e)
m_timer->stop();
}
void FuzzyRotate::leaveEvent(QEvent *e)
{
Q_UNUSED(e)
m_timer->start(1500);
}
四、总结
利用Qt的图形视图框架可以做出许多炫酷复杂的效果,也能满足需要炫酷交互场景的开发。提供了QGraphicsItem
类供我们实现自定义的图形项,这一点非常nice!许多复杂的功能都可以依靠该类来实现!!!
搜索关注【嵌入式小生】wx公众号,回复【1324】即可获取本文源码工程,也可获取更多精彩内容。