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. opencv和javacv版本不一致

    Exception in thread "main" java.lang.UnsatisfiedLinkError: no jniopencv_highgui in java.li ...

  2. Python序列的方法(转)

    在快速教程中,我们了解了最基本的序列(sequence).回忆一下,序列包含有定值表(tuple)和表(list).此外,字符串(string)是一种特殊的定值表.表的元素可以更改,定值表一旦建立,其 ...

  3. 【VS2015正式版下载】Visual Studio 2015 正式版开放下载 Visual Studio 2015 神key

    说明: 微软定于2015年7月20日发布Visual Studio 2015正式版,目前其官方网站已经提供正式版本的下载. 可在https://www.visualstudio.com/en-us/d ...

  4. github 预览html

    在网址前加 http://htmlpreview.github.io/?

  5. java多线层同时运行的解决,同步代码块synchronized

    /* 多个线层同时操作一个数据 会导制数据超出 同步代码块 synchronized(对像) { 需要同步的代码 } */ class Do7 { public static void main(St ...

  6. 《图解CSS3》——笔记(一)

    作者:大漠 勘误:http://www.w3cplus.com/book-comment.html 2014年7月14日14:46:35 第一章  揭开CSS3的面纱 1.1  什么是CSS3 CSS ...

  7. python学习第八天 -- 迭代

    什么是迭代? 在python语言中,迭代的意思就是通过for循环遍历一个有序/无序的集合. 迭代是通过 for x in 集合 来完成的. 前面有提到python中有哪些集合,现在我们来梳理一下: ( ...

  8. Python新手学习基础之函数-全局变量和局部变量

    全局变量和局部变量 我们通常把定义在函数外的变量成为全局变量,定义在函数内的变量称为局部变量,顾名思义,全局变量的作用域是整个代码段,局部变量的作用域就只是在它所属的代码段,变量只在它的作用域里有效. ...

  9. How many ways??(HDU 2157)

    How many ways?? Sample Input 4 4 //n个点,m条路径0 1 //s->t可通0 21 32 32 //询问数0 3 2 //从0到3走两条路可到的方案有多少种0 ...

  10. Qt creator 常用的快捷健

    Qt creator 常用的快捷健 F1        查看帮助F2        跳转到函数定义(和Ctrl+鼠标左键一样的效果)Shift+F2    声明和定义之间切换F4        头文件 ...