Qt使用QGraphicsView实现滑动窗体效果
QGraphicsView用来显示一个滚动视图区的QGraphicsScene内容。QGraphicsScene提供了QGraphicsItem的容器功能。通常与QGraphicsView一起使用来描述可视化图形项目。
QGraphicsScene提供了一个视图的场景,通过在这样一个场景之上加入不同的QGraphicsItem来构建视图。而 QGraphicsView则提供了一个widget来显示QGraphicsScene的内容。所以要想成功构建一个视图,这三个元素缺一不可。
以下是一个QGraphicsView的例子,实现滑动的窗体效果,工具栏和图片均为场景中的Item。
- #include <QtCore>
- #include <QtGui>
- #include <QtSvg>
- /*程序中用到了svg格式的图片,所以需包含QtSvg*/
- #define PAGE_COUNT 5
- /*定义滑动窗体的窗体数*/
定义工具栏,NviBar继承自QGraphicsRectItem,用法与QGraphicsItem类似。
- class NaviBar : public QObject, public QGraphicsRectItem
- {
- Q_OBJECT
- public:
- NaviBar();
- void setPageOffset(qreal ofs);
- signals:
- void pageSelected(int page);
- protected:
- void mousePressEvent(QGraphicsSceneMouseEvent *event);
- void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
- private:
- QList<QGraphicsSvgItem*> m_icons;
- QGraphicsRectItem *m_cursor;
- };
函数实现
- #define ICON_SIZE 50
- #define ICON_PAD 4
- NaviBar::NaviBar()
- : QGraphicsRectItem()
- {
- setRect(0, 0, 5 * ICON_SIZE, ICON_SIZE);
- setPen(Qt::NoPen);
- QStringList names;
- names << "map" << "web" << "home" << "weather" << "contacts";
- for (int i = 0; i < names.count(); ++i) {
- QString fname = names[i];
- fname.prepend(":/icons/");
- fname.append("-page.svg");
- QGraphicsSvgItem *icon = new QGraphicsSvgItem(fname);
- icon->setParentItem(this);
- const int dim = ICON_SIZE - ICON_PAD * 2;
- qreal sw = dim / icon->boundingRect().width();
- qreal sh = dim / icon->boundingRect().height();
- icon->setTransform(QTransform().scale(sw, sh));
- icon->setZValue(2);
- m_icons << icon;
- }
- m_cursor = new QGraphicsRectItem;
- m_cursor->setParentItem(this);
- m_cursor->setRect(0, 0, ICON_SIZE, ICON_SIZE);
- m_cursor->setZValue(1);
- m_cursor->setPen(Qt::NoPen);
- m_cursor->setBrush(QColor(Qt::white));
- m_cursor->setOpacity(0.6);
- }
- void NaviBar::setPageOffset(qreal ofs)
- {
- m_cursor->setPos(ofs * ICON_SIZE, 0);
- for (int i = 0; i < m_icons.count(); ++i) {
- int y = (i == static_cast<int>(ofs + 0.5)) ? ICON_PAD : ICON_PAD * 2;
- m_icons[i]->setPos(i * ICON_SIZE + ICON_PAD, y);
- m_icons[i]->setOpacity(1);
- }
- }
- void NaviBar::mousePressEvent(QGraphicsSceneMouseEvent *event)
- {
- emit pageSelected(static_cast<int>(event->pos().x() / ICON_SIZE));
- }
- void NaviBar::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
- {
- painter->setBrush(Qt::white);
- painter->setOpacity(0.2);
- painter->drawRect(option->rect.adjusted(-20, ICON_PAD, 20, 0));
- }
定义视图
- class ParallaxHome: public QGraphicsView
- {
- Q_OBJECT
- public:
- QGraphicsScene m_scene;
- NaviBar *m_naviBar;
- QGraphicsPixmapItem *m_wallpaper;
- QTimeLine m_pageAnimator;
- qreal m_pageOffset;
- QList<QGraphicsPixmapItem*> m_items;
- QList<QPointF> m_positions;
- public:
- ParallaxHome(QWidget *parent = 0)
- : QGraphicsView(parent)
- , m_pageOffset(-2) {
- setupScene();
- setScene(&m_scene);
- setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
- setFrameShape(QFrame::NoFrame);
- setWindowTitle("Parallax Home");
- connect(&m_pageAnimator, SIGNAL(frameChanged(int)), SLOT(shiftPage(int)));
- m_pageAnimator.setDuration(500);
- m_pageAnimator.setFrameRange(0, 100);
- m_pageAnimator.setCurveShape(QTimeLine::EaseInCurve);
- pageChanged(static_cast<int>(m_pageOffset));
- }
- signals:
- void pageChanged(int page);
- public slots:
- void slideRight() {
- if (m_pageAnimator.state() != QTimeLine::NotRunning)
- return;
- int edge = -(m_pageOffset - 1);
- if (edge < PAGE_COUNT)
- slideBy(-1);
- }
- void slideLeft() {
- if (m_pageAnimator.state() != QTimeLine::NotRunning)
- return;
- if (m_pageOffset < 0)
- slideBy(1);
- }
- void slideBy(int dx) {
- int start = m_pageOffset * 1000;
- int end = (m_pageOffset + dx) * 1000;
- m_pageAnimator.setFrameRange(start, end);
- m_pageAnimator.start();
- }
- void choosePage(int page) {
- if (m_pageAnimator.state() != QTimeLine::NotRunning)
- return;
- if (static_cast<int>(-m_pageOffset) == page)
- return;
- slideBy(-page - m_pageOffset);
- }
- private slots:
- void shiftPage(int frame) {
- int ww = width();
- int hh = height() - m_naviBar->rect().height();
- int oldPage = static_cast<int>(-m_pageOffset);
- m_pageOffset = static_cast<qreal>(frame) / qreal(1000);
- int newPage = static_cast<int>(-m_pageOffset);
- m_naviBar->setPageOffset(-m_pageOffset);
- if (oldPage != newPage)
- emit pageChanged(newPage);
- int ofs = m_pageOffset * ww;
- for (int i = 0; i < m_items.count(); ++i) {
- QPointF pos = m_positions[i];
- QPointF xy(pos.x() * ww, pos.y() * hh);
- m_items[i]->setPos(xy + QPointF(ofs, 0));
- }
- int center = m_wallpaper->pixmap().width() / 2;
- const int parallax = 3;
- int base = center - (ww / 2) - (PAGE_COUNT >> 1) * (ww / parallax);
- int wofs = base - m_pageOffset * ww / parallax;
- m_wallpaper->setPos(-wofs, 0);
- }
- protected:
- void resizeEvent(QResizeEvent *event) {
- Q_UNUSED(event);
- layoutScene();
- }
- void keyPressEvent(QKeyEvent *event) {
- if (event->key() == Qt::Key_Right)
- slideRight();
- if (event->key() == Qt::Key_Left)
- slideLeft();
- event->accept();
- }
- private:
- void layoutScene() {
- int ww = width();
- int hh = height();
- m_scene.setSceneRect(0, 0, PAGE_COUNT * ww - 1, hh - 1);
- centerOn(ww / 2, hh / 2);
- int nw = m_naviBar->rect().width();
- int nh = m_naviBar->rect().height();
- m_naviBar->setPos((ww - nw) / 2, hh - nh);
- shiftPage(m_pageOffset * 1000);
- }
- void setupScene() {
- qsrand(QTime::currentTime().second());
- QStringList names;
- names << "brownies" << "cookies" << "mussels" << "pizza" << "sushi";
- names << "chocolate" << "fish" << "pasta" << "puding" << "trouts";
- for (int i = 0; i < PAGE_COUNT * 2; ++i) {
- QString fname = names[i];
- fname.prepend(":/images/");
- fname.append(".jpg");
- QPixmap pixmap(fname);
- pixmap = pixmap.scaledToWidth(200);
- QGraphicsPixmapItem *item = m_scene.addPixmap(pixmap);
- m_items << item;
- qreal x = (i >> 1) + (qrand() % 30) / 100.0;
- qreal y = (i & 1) / 2.0 + (qrand() % 20) / 100.0;
- m_positions << QPointF(x, y);
- item->setZValue(1);
- }
- m_naviBar = new NaviBar;
- m_scene.addItem(m_naviBar);
- m_naviBar->setZValue(2);
- connect(m_naviBar, SIGNAL(pageSelected(int)), SLOT(choosePage(int)));
- m_wallpaper = m_scene.addPixmap(QPixmap(":/icons/surfacing.png"));
- m_wallpaper->setZValue(0);
- m_scene.setItemIndexMethod(QGraphicsScene::NoIndex);
- }
- };
main函数
- #include "parallaxhome.moc"
- int main(int argc, char *argv[])
- {
- QApplication app(argc, argv);
- ParallaxHome w;
- w.resize(360, 640);
- w.show();
- return app.exec();
- }
效果图
Qt使用QGraphicsView实现滑动窗体效果的更多相关文章
- animate 实现滑动切换效果
今天和大家分享一下用 animate 实现滑动切换效果的小例子 ------- 来自<一只有梦想的前端小白> 大家都知道jQuery 提供的有一下几种方法能够实现滑动效果: slideDo ...
- Android实现滑动刻度尺效果,选择身高体重和生日
刻度尺效果虽然看起来很美,我个人认为很不实用,即使再不实用,也有用的,鉴于群里成员对我的苦苦哀求,我就分享一个他用不到的,横屏滑动刻度尺,因为他需要竖屏的,哈哈…… 最近群里的开发人员咨询怎样实现刻度 ...
- Android UI效果实现——Activity滑动退出效果
更新说明: 1.在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable.focusableInTouch.clickable的状态设置,否则会导致部分情况 ...
- iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果
8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...
- 【转】Android 实现ListView的滑动删除效果
http://www.cnblogs.com/weixiao870428/p/3524055.html http://download.csdn.net/download/love_javc_you/ ...
- Android实现左右滑动指引效果
本文介绍Android中实现左右滑动的指引效果. 关于左右滑动效果,我在以前的一篇博文中提到过,有兴趣的朋友可以查看:http://www.cnblogs.com/hanyonglu/archive/ ...
- 个人学习JQ插件编写成果:little酷炫的图片滑动切换效果
工作一个多月了,好久没来冒冒泡了,看了@wayong的JQ插件教程,自己编写了一个模仿拉勾网首页广告栏滑动特效的JQ插件,现在跟朋友们分享分享! 先上demo链接:http://runjs.cn/de ...
- [Android] Android 类似今日头条顶部的TabLayout 滑动标签栏 效果
APP市场中大多数新闻App都有导航菜单,导航菜单是一组标签的集合,在新闻客户端中,每个标签标示一个新闻类别,对应下面ViewPager控件的一个分页面,今日头条, 网易新闻等. 本文主要讲的是用:T ...
- 基于vue项目的组件中导入mui框架初始化滑动等效果时需移除严格模式的问题
基于vue项目的组件中导入mui框架初始化滑动等效果时,控制台报错:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties ...
随机推荐
- GitHub 小试
GitHub是什么? 它是用来进行版本控制的,就是用来保存项目的地方. 但是项目要是运行,还是需要你本地的环境,它只不过是用来保存代码罢了. GitHub如何操作? 可以通过客户端进行代码提交,更新. ...
- openwrt sdk compile
recently ,bought a router : tl-wr741n-v5 hd my aim : let the router dail in neetkeeper environment : ...
- 小学生之KTV播放原理
第一步: 创建一个Song类 //歌曲名称 public string SongName { get; set; } //歌曲路劲 public string SongPath { get; set ...
- 网站项目后台的目录命名为admin后,网页莫名其妙的变样了
这是我的第一篇博客文章,与其说是分享经验,倒不如说是求助 最近因为要完成一个课程设计,在拿一个现成的项目过来改,要用到select下拉菜单,可是发觉怎么我的这个下拉菜单怎么变样了 刚开始它是这样的 感 ...
- Java NIO框架Netty教程(一) – Hello Netty
先啰嗦两句,如果你还不知道Netty是做什么的能做什么.那可以先简单的搜索了解一下.我只能说Netty是一个NIO的框架,可以用于开发分布式的Java程序.具体能做什么,各位可以尽量发挥想象.技术,是 ...
- 模板模式(Template)
行为型:Template(模板模式) 作为一个曾经爱好写文章,但是不太懂得写文章的人,我必须承认,开头是个比较难的起步. 模板模式常规定义:模板模式定义了一个算法步骤,把实现延迟到子类. 事实上模板模 ...
- 打破C++ Const 的规则
从一个C++菜鸟改函数开始 CString MyClass::GetStringValue() const { return m_strValue; } 这个值可能还没有赋值,好吧,那么我先判断是不是 ...
- linux下enum的使用
enum T { status1, status2, } Linux下: 1.做函数返回值时enum T f():不能写成T f(): 2.if(i == status1)不能写成 if(i == T ...
- HTML&CSS基础学习笔记1.8-预格式文本
<pre>标签的主要作用是预格式化文本.被包围在 pre 标签中的文本通常会保留空格和换行符.而文本也会呈现为等宽字体. <pre>标签的一个常见应用就是用来表示计算机的源代码 ...
- C/C++ char和int的区别
字符字面值一般是用一对单引号来表示.char类型一般就是用字符字面值来初始化.赋值.由于char类型的是单字节长度,当给char类型的变量用字符字面值赋值时,当单引号里面的内容超过一个字节时,系统会自 ...