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_vs2013\Examples\Qt-5.7\quick\customitems\maskedmousearea目錄下。我使用的qt5.6.1-1版本,該版本為自行編譯版本,編譯參考:msvc2013編譯qt5.6源碼

三、相關文章

  qml demo分析(abstractitemmodel-數據分離)

  qml demo分析(clocks-時鍾)

  qml demo分析(customgeometry-貝塞爾曲線)

  qml demo分析(maroon-小游戲)

 

如果您覺得文章不錯,不妨給個打賞,寫作不易,感謝各位的支持。您的支持是我最大的動力,謝謝!!! 

 

  


很重要--轉載聲明

  1. 本站文章無特別說明,皆為原創,版權所有,轉載時請用鏈接的方式,給出原文出處。同時寫上原作者:朝十晚八 or Twowords
  2. 如要轉載,請原文轉載,如在轉載時修改本文,請事先告知,謝絕在轉載時通過修改本文達到有利於轉載者的目的。 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM