• 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. 如要转载,请原文转载,如在转载时修改本文,请事先告知,谢绝在转载时通过修改本文达到有利于转载者的目的。 

  • 相关阅读:
    Python标准库 -- UUID模块(生成唯一标识)
    Python全局解释器锁 -- GIL
    Python Web Server Gateway Interface -- WSGI
    Mysql 和 Postgresql 抛开性能的对比
    一篇文章掌握RequireJS常用知识
    彻底理解js中的闭包
    全面理解Javascript闭包和闭包的几种写法及用途【转】
    JS 日期转换,格式化等常用的函数定义
    把上传过来的多张图片拼接转为PDF的实现代码
    C# Stream 和 byte[] 之间的转换(文件流的应用)
  • 原文地址:https://www.cnblogs.com/swarmbees/p/6519613.html
Copyright © 2020-2023  润新知