zoukankan      html  css  js  c++  java
  • qml demo分析(maskedmousearea-异形窗口)

    一、效果展示

      如本文的标题所示,这篇文章分析的demo是一个异形窗口,主要展示鼠标在和异形区域交互的使用,效果如图1所示,当鼠标移动到白云或者月亮上时,相应的物体会高亮,当鼠标按下时,物体会有一个放大的动画效果,鼠标离开时恢复原样。

    图1 月亮和云朵

    二、源码分析

       正式算起来,这是我分析的第五篇qml示例程序了,在这里他么有一个共同点,qml控件直接展示不了的东西都是使用C++类或者js函数来完成,比如这篇文章要讲的异形区域判断;qml demo分析(customgeometry-贝塞尔曲线)文章中的贝塞尔曲线绘制;qml demo分析(maroon-小游戏)小游戏中的代码复杂逻辑使用js控制;qml demo分析(abstractitemmodel-数据分离)示例中的model结构等。那么从这几篇文章中我们也能体会到qml不是一个人在战斗,他更多的是在于ui展示,而具体的逻辑或者更为复杂的操作需要交给C++程序或者js代码来完成,关于C++和qml混合编程、js和qml混合编程之前的代码都有涉及,不了解的同学可以直接点击相关链接进入。

      本篇示例代码相对来说比较简单,主要就是两部分:qml和C++

    1、qml代码

      qml代码中总共有3张图片,先添加的图片在下层显示,如果你想要让某一张图片在上次显示那么就需要在最后添加该组件。这3张图片的行为是一模一样,因此我只分析月亮这一个组件,代码如下

     1     //后添加的元素在上
     2     Image {
     3         id: moon
     4         anchors.centerIn: parent
     5         scale: moonArea.pressed ? 1.1 : 1.0//按下时  放大  
     6         opacity: moonArea.containsMouse ? 1.0 : 0.7//hover时 无透明度
     7         source: Qt.resolvedUrl("images/moon.png")
     8 
     9         MaskedMouseArea {//自定义组件   新增鼠标是否按下判断、鼠标是否在区域内 
    10             id: moonArea
    11             anchors.fill: parent
    12             alphaThreshold: 0
    13             maskSource: moon.source
    14         }
    15 
    16         Behavior on opacity {//透明度使用渐变
    17             NumberAnimation { duration: 200 }
    18         }
    19         Behavior on scale {//放大使用渐变
    20             NumberAnimation { duration: 100 }
    21         }
    22     }

      上述代码就是qml中关于月亮的展示,MaskedMouseArea组件是使用qmlRegisterType宏注册到qml系统中的。本篇文章我就不在讲解main函数了,如果忘记的同学可以到qml demo分析(customgeometry-贝塞尔曲线)文章中回顾。

    2、C++代码

      本篇文章有一个自定义的C++类,主要是给qml程序提供鼠标按下、鼠标hover等状态,头文件如下

     1 #include <QImage>
     2 #include <QQuickItem>
     3 
     4 class MaskedMouseArea : public QQuickItem
     5 {
     6     Q_OBJECT
     7     Q_PROPERTY(bool pressed READ isPressed NOTIFY pressedChanged)
     8     Q_PROPERTY(bool containsMouse READ containsMouse NOTIFY containsMouseChanged)
     9     Q_PROPERTY(QUrl maskSource READ maskSource WRITE setMaskSource NOTIFY maskSourceChanged)
    10     Q_PROPERTY(qreal alphaThreshold READ alphaThreshold WRITE setAlphaThreshold NOTIFY alphaThresholdChanged)
    11 
    12 public:
    13     MaskedMouseArea(QQuickItem *parent = 0);
    14 
    15     bool contains(const QPointF &point) const;//重写contains接口 判断鼠标是否在在异形窗口内 默认实现判断参数点是否在bounding rect内
    16 
    17     //鼠标是否按下 配合Q_PROPERTY宏  可以被qml系统调用 例如:scale: rightCloudArea.pressed ? 1.1 : 1.0
    18     bool isPressed() const { return m_pressed; }
    19     bool containsMouse() const { return m_containsMouse; }
    20 
    21     QUrl maskSource() const { return m_maskSource; }
    22     void setMaskSource(const QUrl &source);
    23 
    24     qreal alphaThreshold() const { return m_alphaThreshold; }
    25     void setAlphaThreshold(qreal threshold);
    26 
    27 signals:
    28     void pressed();//自定义信号  在qml系统中均有OnPressed槽
    29     void released();
    30     void clicked();
    31     void canceled();
    32     void pressedChanged();
    33     void maskSourceChanged();
    34     void containsMouseChanged();
    35     void alphaThresholdChanged();
    36 
    37 protected:
    38     void setPressed(bool pressed);
    39     void setContainsMouse(bool containsMouse);
    40 
    41     void mousePressEvent(QMouseEvent *event);
    42     void mouseReleaseEvent(QMouseEvent *event);
    43 
    44     void hoverEnterEvent(QHoverEvent *event);
    45     void hoverLeaveEvent(QHoverEvent *event);
    46 
    47     void mouseUngrabEvent();
    48 
    49 private:
    50     bool m_pressed;
    51     QUrl m_maskSource;
    52     QImage m_maskImage;
    53     QPointF m_pressPoint;
    54     qreal m_alphaThreshold;
    55     bool m_containsMouse;
    56 };

      头文件中的Q_PROPERTY如果忘记其含义,可以到qml demo分析(customgeometry-贝塞尔曲线)文章中了解,其中每一个Q_PROPERTY宏第一个参数为属性,READ指定读取属性的接口,WRITE指定设置属性的接口,NOTIFY指定当属性改变时所触发的信号,当然了这个属性还有更多的其他功能,感兴趣的同学可以自行上帮助文档查阅。

     1 bool MaskedMouseArea::contains(const QPointF &point) const
     2 {
     3     if (!QQuickItem::contains(point) || m_maskImage.isNull())
     4         return false;
     5 
     6     QPoint p = point.toPoint();
     7 
     8     if (p.x() < 0 || p.x() >= m_maskImage.width() ||
     9         p.y() < 0 || p.y() >= m_maskImage.height())
    10         return false;
    11 
    12     qreal r = qBound<int>(0, m_alphaThreshold * 255, 255);
    13     return qAlpha(m_maskImage.pixel(p)) > r;//根据alpha值判断 异形区域
    14 }

      自定义QQuickItem类,最重要的是判断鼠标是否在区域内,也就是contains函数,该函数默认是判断鼠标是否在组件所在矩形区域,为了让交互行为更好,我们需要让鼠标在月亮的圆上或者云朵内才高亮物体,因此我们重写了次接口,该接口是用图片的alpha值来判断,当该值达到一定透明度时,认为其不在区域内,具体代码如上所示。

      这篇示例代码在Qt5.7.0_vs2013ExamplesQt-5.7quickcustomitemsmaskedmousearea目录下。我使用的qt5.6.1-1版本,该版本为自行编译版本,编译参考:msvc2013编译qt5.6源码

    三、相关文章

      qml demo分析(abstractitemmodel-数据分离)

      qml demo分析(clocks-时钟)

      qml demo分析(customgeometry-贝塞尔曲线)

      qml demo分析(maroon-小游戏)

    如果您觉得文章不错,不妨给个打赏,写作不易,感谢各位的支持。您的支持是我最大的动力,谢谢!!! 

     

      


    很重要--转载声明

    1. 本站文章无特别说明,皆为原创,版权所有,转载时请用链接的方式,给出原文出处。同时写上原作者:朝十晚八 or Twowords
    2. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。 

  • 相关阅读:
    hihoCoder #1062 : 最近公共祖先·一
    hihoCoder #1050 : 树中的最长路
    hihoCoder #1049 : 后序遍历
    108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
    107 Binary Tree Level Order Traversal II 二叉树的层次遍历 II
    106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
    105 Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
    104 Maximum Depth of Binary Tree 二叉树的最大深度
    102 Binary Tree Level Order Traversal 二叉树的层次遍历
    101 Symmetric Tree 判断一颗二叉树是否是镜像二叉树
  • 原文地址:https://www.cnblogs.com/swarmbees/p/6519613.html
Copyright © 2011-2022 走看看