QGraphicsView用来显示一个滚动视图区的QGraphicsScene内容。QGraphicsScene提供了QGraphicsItem的容器功能。通常与QGraphicsView一起使用来描述可视化图形项目。

QGraphicsScene提供了一个视图的场景,通过在这样一个场景之上加入不同的QGraphicsItem来构建视图。而 QGraphicsView则提供了一个widget来显示QGraphicsScene的内容。所以要想成功构建一个视图,这三个元素缺一不可。

以下是一个QGraphicsView的例子,实现滑动的窗体效果,工具栏和图片均为场景中的Item。

  1. #include <QtCore>
  2. #include <QtGui>
  3. #include <QtSvg>
  4. /*程序中用到了svg格式的图片,所以需包含QtSvg*/
  5. #define PAGE_COUNT 5
  6. /*定义滑动窗体的窗体数*/

定义工具栏,NviBar继承自QGraphicsRectItem,用法与QGraphicsItem类似。

  1. class NaviBar : public QObject, public QGraphicsRectItem
  2. {
  3. Q_OBJECT
  4. public:
  5. NaviBar();
  6. void setPageOffset(qreal ofs);
  7. signals:
  8. void pageSelected(int page);
  9. protected:
  10. void mousePressEvent(QGraphicsSceneMouseEvent *event);
  11. void paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget = 0);
  12. private:
  13. QList<QGraphicsSvgItem*> m_icons;
  14. QGraphicsRectItem *m_cursor;
  15. };

函数实现

  1. #define ICON_SIZE 50
  2. #define ICON_PAD 4
  3. NaviBar::NaviBar()
  4. : QGraphicsRectItem()
  5. {
  6. setRect(0, 0, 5 * ICON_SIZE, ICON_SIZE);
  7. setPen(Qt::NoPen);
  8. QStringList names;
  9. names << "map" << "web" << "home" << "weather" << "contacts";
  10. for (int i = 0; i < names.count(); ++i) {
  11. QString fname = names[i];
  12. fname.prepend(":/icons/");
  13. fname.append("-page.svg");
  14. QGraphicsSvgItem *icon = new QGraphicsSvgItem(fname);
  15. icon->setParentItem(this);
  16. const int dim = ICON_SIZE - ICON_PAD * 2;
  17. qreal sw = dim / icon->boundingRect().width();
  18. qreal sh = dim / icon->boundingRect().height();
  19. icon->setTransform(QTransform().scale(sw, sh));
  20. icon->setZValue(2);
  21. m_icons << icon;
  22. }
  23. m_cursor = new QGraphicsRectItem;
  24. m_cursor->setParentItem(this);
  25. m_cursor->setRect(0, 0, ICON_SIZE, ICON_SIZE);
  26. m_cursor->setZValue(1);
  27. m_cursor->setPen(Qt::NoPen);
  28. m_cursor->setBrush(QColor(Qt::white));
  29. m_cursor->setOpacity(0.6);
  30. }
  31. void NaviBar::setPageOffset(qreal ofs)
  32. {
  33. m_cursor->setPos(ofs * ICON_SIZE, 0);
  34. for (int i = 0; i < m_icons.count(); ++i) {
  35. int y = (i == static_cast<int>(ofs + 0.5)) ? ICON_PAD : ICON_PAD * 2;
  36. m_icons[i]->setPos(i * ICON_SIZE + ICON_PAD, y);
  37. m_icons[i]->setOpacity(1);
  38. }
  39. }
  40. void NaviBar::mousePressEvent(QGraphicsSceneMouseEvent *event)
  41. {
  42. emit pageSelected(static_cast<int>(event->pos().x() / ICON_SIZE));
  43. }
  44. void NaviBar::paint(QPainter * painter, const QStyleOptionGraphicsItem *option, QWidget *widget)
  45. {
  46. painter->setBrush(Qt::white);
  47. painter->setOpacity(0.2);
  48. painter->drawRect(option->rect.adjusted(-20, ICON_PAD, 20, 0));
  49. }

定义视图

  1. class ParallaxHome: public QGraphicsView
  2. {
  3. Q_OBJECT
  4. public:
  5. QGraphicsScene m_scene;
  6. NaviBar *m_naviBar;
  7. QGraphicsPixmapItem *m_wallpaper;
  8. QTimeLine m_pageAnimator;
  9. qreal m_pageOffset;
  10. QList<QGraphicsPixmapItem*> m_items;
  11. QList<QPointF> m_positions;
  12. public:
  13. ParallaxHome(QWidget *parent = 0)
  14. : QGraphicsView(parent)
  15. , m_pageOffset(-2) {
  16. setupScene();
  17. setScene(&m_scene);
  18. setHorizontalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  19. setVerticalScrollBarPolicy(Qt::ScrollBarAlwaysOff);
  20. setFrameShape(QFrame::NoFrame);
  21. setWindowTitle("Parallax Home");
  22. connect(&m_pageAnimator, SIGNAL(frameChanged(int)), SLOT(shiftPage(int)));
  23. m_pageAnimator.setDuration(500);
  24. m_pageAnimator.setFrameRange(0, 100);
  25. m_pageAnimator.setCurveShape(QTimeLine::EaseInCurve);
  26. pageChanged(static_cast<int>(m_pageOffset));
  27. }
  28. signals:
  29. void pageChanged(int page);
  30. public slots:
  31. void slideRight() {
  32. if (m_pageAnimator.state() != QTimeLine::NotRunning)
  33. return;
  34. int edge = -(m_pageOffset - 1);
  35. if (edge < PAGE_COUNT)
  36. slideBy(-1);
  37. }
  38. void slideLeft() {
  39. if (m_pageAnimator.state() != QTimeLine::NotRunning)
  40. return;
  41. if (m_pageOffset < 0)
  42. slideBy(1);
  43. }
  44. void slideBy(int dx) {
  45. int start = m_pageOffset * 1000;
  46. int end = (m_pageOffset + dx) * 1000;
  47. m_pageAnimator.setFrameRange(start, end);
  48. m_pageAnimator.start();
  49. }
  50. void choosePage(int page) {
  51. if (m_pageAnimator.state() != QTimeLine::NotRunning)
  52. return;
  53. if (static_cast<int>(-m_pageOffset) == page)
  54. return;
  55. slideBy(-page - m_pageOffset);
  56. }
  57. private slots:
  58. void shiftPage(int frame) {
  59. int ww = width();
  60. int hh = height() - m_naviBar->rect().height();
  61. int oldPage = static_cast<int>(-m_pageOffset);
  62. m_pageOffset = static_cast<qreal>(frame) / qreal(1000);
  63. int newPage = static_cast<int>(-m_pageOffset);
  64. m_naviBar->setPageOffset(-m_pageOffset);
  65. if (oldPage != newPage)
  66. emit pageChanged(newPage);
  67. int ofs = m_pageOffset * ww;
  68. for (int i = 0; i < m_items.count(); ++i) {
  69. QPointF pos = m_positions[i];
  70. QPointF xy(pos.x() * ww, pos.y() * hh);
  71. m_items[i]->setPos(xy + QPointF(ofs, 0));
  72. }
  73. int center = m_wallpaper->pixmap().width() / 2;
  74. const int parallax = 3;
  75. int base = center - (ww / 2) - (PAGE_COUNT >> 1) * (ww / parallax);
  76. int wofs = base - m_pageOffset * ww / parallax;
  77. m_wallpaper->setPos(-wofs, 0);
  78. }
  79. protected:
  80. void resizeEvent(QResizeEvent *event) {
  81. Q_UNUSED(event);
  82. layoutScene();
  83. }
  84. void keyPressEvent(QKeyEvent *event) {
  85. if (event->key() == Qt::Key_Right)
  86. slideRight();
  87. if (event->key() == Qt::Key_Left)
  88. slideLeft();
  89. event->accept();
  90. }
  91. private:
  92. void layoutScene() {
  93. int ww = width();
  94. int hh = height();
  95. m_scene.setSceneRect(0, 0, PAGE_COUNT * ww - 1, hh - 1);
  96. centerOn(ww / 2, hh / 2);
  97. int nw = m_naviBar->rect().width();
  98. int nh = m_naviBar->rect().height();
  99. m_naviBar->setPos((ww - nw) / 2, hh - nh);
  100. shiftPage(m_pageOffset * 1000);
  101. }
  102. void setupScene() {
  103. qsrand(QTime::currentTime().second());
  104. QStringList names;
  105. names << "brownies" << "cookies" << "mussels" << "pizza" << "sushi";
  106. names << "chocolate" << "fish" << "pasta" << "puding" << "trouts";
  107. for (int i = 0; i < PAGE_COUNT * 2; ++i) {
  108. QString fname = names[i];
  109. fname.prepend(":/images/");
  110. fname.append(".jpg");
  111. QPixmap pixmap(fname);
  112. pixmap = pixmap.scaledToWidth(200);
  113. QGraphicsPixmapItem *item = m_scene.addPixmap(pixmap);
  114. m_items << item;
  115. qreal x = (i >> 1) + (qrand() % 30) / 100.0;
  116. qreal y = (i & 1) / 2.0  + (qrand() % 20) / 100.0;
  117. m_positions << QPointF(x, y);
  118. item->setZValue(1);
  119. }
  120. m_naviBar = new NaviBar;
  121. m_scene.addItem(m_naviBar);
  122. m_naviBar->setZValue(2);
  123. connect(m_naviBar, SIGNAL(pageSelected(int)), SLOT(choosePage(int)));
  124. m_wallpaper = m_scene.addPixmap(QPixmap(":/icons/surfacing.png"));
  125. m_wallpaper->setZValue(0);
  126. m_scene.setItemIndexMethod(QGraphicsScene::NoIndex);
  127. }
  128. };

main函数

  1. #include "parallaxhome.moc"
  2. int main(int argc, char *argv[])
  3. {
  4. QApplication app(argc, argv);
  5. ParallaxHome w;
  6. w.resize(360, 640);
  7. w.show();
  8. return app.exec();
  9. }

效果图

原文:http://blog.csdn.net/huihui1988/article/details/5725955

Qt使用QGraphicsView实现滑动窗体效果的更多相关文章

  1. animate 实现滑动切换效果

    今天和大家分享一下用 animate 实现滑动切换效果的小例子 ------- 来自<一只有梦想的前端小白> 大家都知道jQuery 提供的有一下几种方法能够实现滑动效果: slideDo ...

  2. Android实现滑动刻度尺效果,选择身高体重和生日

    刻度尺效果虽然看起来很美,我个人认为很不实用,即使再不实用,也有用的,鉴于群里成员对我的苦苦哀求,我就分享一个他用不到的,横屏滑动刻度尺,因为他需要竖屏的,哈哈…… 最近群里的开发人员咨询怎样实现刻度 ...

  3. Android UI效果实现——Activity滑动退出效果

    更新说明: 1.在QQ网友北京-旭的提醒下,在SlideFrame的initilize方法中添加了focusable.focusableInTouch.clickable的状态设置,否则会导致部分情况 ...

  4. iOS开发——实用技术OC篇&8行代码教你搞定导航控制器全屏滑动返回效果

    8行代码教你搞定导航控制器全屏滑动返回效果 前言 如果自定了导航控制器的自控制器的leftBarButtonItem,可能会引发边缘滑动pop效果的失灵,是由于 self.interactivePop ...

  5. 【转】Android 实现ListView的滑动删除效果

    http://www.cnblogs.com/weixiao870428/p/3524055.html http://download.csdn.net/download/love_javc_you/ ...

  6. Android实现左右滑动指引效果

    本文介绍Android中实现左右滑动的指引效果. 关于左右滑动效果,我在以前的一篇博文中提到过,有兴趣的朋友可以查看:http://www.cnblogs.com/hanyonglu/archive/ ...

  7. 个人学习JQ插件编写成果:little酷炫的图片滑动切换效果

    工作一个多月了,好久没来冒冒泡了,看了@wayong的JQ插件教程,自己编写了一个模仿拉勾网首页广告栏滑动特效的JQ插件,现在跟朋友们分享分享! 先上demo链接:http://runjs.cn/de ...

  8. [Android] Android 类似今日头条顶部的TabLayout 滑动标签栏 效果

    APP市场中大多数新闻App都有导航菜单,导航菜单是一组标签的集合,在新闻客户端中,每个标签标示一个新闻类别,对应下面ViewPager控件的一个分页面,今日头条, 网易新闻等. 本文主要讲的是用:T ...

  9. 基于vue项目的组件中导入mui框架初始化滑动等效果时需移除严格模式的问题

    基于vue项目的组件中导入mui框架初始化滑动等效果时,控制台报错:Uncaught TypeError: 'caller', 'callee', and 'arguments' properties ...

随机推荐

  1. Protobuf实现Android Socket通讯开发教程

    本节为您介绍Protobuf实现Android Socket通讯开发教程,因此,我们需要先了理一下protobuf 是什么? Protocol buffers是一种编码方法构造的一种有效而可扩展的格式 ...

  2. C语言union关键字

    union 关键字的用法与struct 的用法非常类似. union 维护足够的空间来置放多个数据成员中的“一种”,而不是为每一个数据成员配置空间,在union 中所有的数据成员共用一个空间,同一时间 ...

  3. css布局&初始化&基准样式

    学习css布局比较好的网站 学习css布局 1.css设置模块 typography(字体) colour(颜色) link(链接) forms(表单) layout(布局) navigation(导 ...

  4. Dialog( 对话框) 组件

    一. 加载方式//class 加载方式<div class="easyui-dialog" title="My Dialog"style="wi ...

  5. HTML基础总结<文本格式>

    HTML 文本格式化标签 标签 描述 <b> 定义粗体文本 <em> 呈现为被强调的文本 <i> 定义斜体字 <small> 定义小号字 <str ...

  6. 初学Java ssh之Spring 第一篇

    之前虽然毕业前实习的工作是使用的C# .NET语言,但是,毕业后还是果断应聘Java.虽然自己对Java的理解不如C#深入,只是对基础知识比较熟悉,但还是义无返顾了··· 虽然应聘经历比较坎坷,但最终 ...

  7. java新版中唤醒指定线层对象

    import java.util.concurrent.locks.*; class Do9 { public static void main(String[] args) { Resource r ...

  8. (五)JS学习笔记 - JQuery缓存机制

    历史背景 开发中常常因为方便,把状态标志都写到dom节点中,也就是HTMLElement,缺点: 循环引用 直接暴露数据,安全性? 增加一堆的自定义属性标签,对浏览器来说是没意义的 取数据的时候要对H ...

  9. Git学习笔记01--初始化设置

    1.查看git版本 $ git --version 2.设置用户姓名和邮箱 $ git config --global user.name “Craftor” $ git config --globa ...

  10. soapUI通过groovy脚本设置超时时间

    import com.eviware.soapui.SoapUI import com.eviware.soapui.settings.HttpSettings import com.eviware. ...