QML中的MouseArea類型為用戶進行簡單的鼠標操作提供了方便。
MouseArea是一個不可見的Item,通常與可見項目結合使用,以便為該項目提供鼠標處理。通過有效地充當代理,鼠標處理的邏輯可以包含在MouseArea Item中。
MouseArea雖然是一個不可見的Item,但是它有一個“visible”屬性,當該屬性為假時,鼠標區域就對鼠標事件變得透明。
MouseArea使用實例:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 |
import
QtQuick
2
.
12
import QtQuick.Window 2 . 12 Window { id : window visible : true width : 640 height : 480 title : qsTr( "Mouse Area" ) Rectangle { id : rect anchors.left : window.left anchors.leftMargin : 10 width : 100 ; height : 100 color : "green" MouseArea { anchors.fill : parent onClicked : { parent.color = 'red' ; } } } Rectangle { id : roundrect anchors.left : rect.right anchors.leftMargin : 10 width : 100 ; height : 100 color : "red" radius : 20 MouseArea { anchors.fill : parent onClicked : { parent.color = 'green' } } } } |
常規測試實驗證實,MouseArea有一個矩形的形狀區域,這就會導致一些不是矩形形狀的Item不能有效地獲取實際形狀的鼠標操作區域。如圓角矩形,在圓形按鈕周圍的假想方塊的角落的鼠標操作也會被捕獲,這顯然不符合精准拾取的現實。
進階地,文章“How to create a round mouse area in QML “提供了一種圓形鼠標區域RoundMouseArea:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
import
QtQuick
2
.
0
Item { id: roundMouseArea property alias mouseX: mouseArea.mouseX property alias mouseY: mouseArea.mouseY property bool containsMouse: { var x1 = width / 2 ; var y1 = height / 2 ; var x2 = mouseX; var y2 = mouseY; var distanceFromCenter = Math.pow(x1 - x2, 2 ) + Math.pow(y1 - y2, 2 ); var radiusSquared = Math.pow(Math.min(width, height) / 2 , 2 ); var isWithinOurRadius = distanceFromCenter < radiusSquared; return isWithinOurRadius; } readonly property bool pressed: containsMouse && mouseArea.pressed signal clicked MouseArea { id: mouseArea anchors.fill: parent hoverEnabled: true acceptedButtons: Qt.LeftButton | Qt.RightButton onClicked: if (roundMouseArea.containsMouse) roundMouseArea.clicked() } } |
main.qml中使用:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
RoundMouseArea {
id : roundMouseArea width : 100 height : 100 anchors.centerIn : parent onClicked : print( "clicked" ) // Show the boundary of the area and whether or not it's hovered. Rectangle { color : roundMouseArea.pressed ? "red" : (roundMouseArea.containsMouse ? "darkorange" : "transparent" ) border.color : "darkorange" radius : width / 2 anchors.fill : parent } } |
我們可以根據需要重寫containsMouse來規定自己的鼠標區域,但是需要計算不同區域的數學知識,需要一定的功底。
再進一步,應該把鼠標區域一般化,可以使用任意的路徑形狀來表示才好。Qt自帶一個例子maskedmousearea,此示例提供了一種使用任何形狀的Mask的方法,它可以根據您的需求進行定制。
先睹為快:
該demo是一個異形窗口,主要展示鼠標在和異形區域交互的使用,如上圖所示,當鼠標移動到白雲或者月亮上時,相應的物體會高亮,當鼠標按下時,物體會有一個放大的動畫效果,鼠標離開時恢復原樣。
class MaskedMouseArea : public QQuickItem
核心主要時判斷鼠標點是否在圖片有效區域內:
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
bool
MaskedMouseArea::contains(
const
QPointF &point)
const
{ if (!QQuickItem::contains(point) || m_maskImage.isNull()) return false ; QPoint p = point.toPoint(); if (p.x() < 0 || p.x() >= m_maskImage.width() || p.y() < 0 || p.y() >= m_maskImage.height()) return false ; qreal r = qBound< int >( 0 , m_alphaThreshold * 255 , 255 ); //根據alpha值判斷 異形區域 return qAlpha(m_maskImage.pixel(p)) > r; } |
1
2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
Image {
id : moon anchors.centerIn : parent scale : moonArea.pressed ? 1 . 1 : 1 . 0 opacity : moonArea.containsMouse ? 1 . 0 : 0 . 7 source : Qt.resolvedUrl( "images/moon.png" ) MaskedMouseArea { id : moonArea anchors.fill : parent alphaThreshold : 0 . 4 maskSource : moon.source } Behavior on opacity { NumberAnimation { duration : 200 } } Behavior on scale { NumberAnimation { duration : 100 } } } |
gif走起來: