源于一个Qml项目需求。需要在界面显示菜单栏,但菜单栏需要根据控件的所在位置显示。如下演示:
点击详情(detail)按钮调出菜单列表。菜单栏的位置需要定位详情按钮的下面,那么就需要知道具体坐标。
由于Qml控件的坐标是相对坐标(相对于父控件的坐标),既然是相对父控件的坐标,那么我们遍历所有父控件的坐标进行累加就可以计算出该控件的全局坐标了。
实现代码
代码语言:javascript复制function getGlobalPosition(targetObject) {
var positionX = 0
var positionY = 0
var obj = targetObject
/* 遍历所有的父窗口 */
while (obj != null) {
/* 累加计算坐标 */
positionX = obj.x
positionY = obj.y
obj = obj.parent
}
return {"x": positionX, "y": positionY}
}
演示例子代码
代码语言:javascript复制import QtQuick 2.0
Rectangle {
id: root
anchors.fill: parent
color: "white"
/* 网格视图 */
GridView {
id: gridView
anchors.centerIn: parent
width: parent.width / 2
height: parent.height / 2
/* 设置单元格大小 */
cellWidth: width / 2
cellHeight: height / 2
model: 4
delegate: Item {
id: itemDelegate
width: gridView.cellWidth
height: gridView.cellHeight
Column {
id: column
anchors.centerIn: parent
width: parent.width - 20
height: parent.height - 20
spacing: 10
/* 内容方框 */
Rectangle {
width: parent.width
height: parent.height * 3 / 4
color: "#00000000"
border.color: "#d5d5d5"
Column {
x: 10; y: 10
Text {
text: "Title1"
font.pixelSize: 15
}
Text {
text: "Sub title2"
font.pixelSize: 13
}
}
Text {
anchors.right: parent.right
anchors.bottom: parent.bottom
anchors.rightMargin: 8
anchors.bottomMargin: 8
text: "==="
font.pixelSize: 13
}
MouseArea {
anchors.fill: parent
onClicked: {}
}
}
/* 圆形详情按钮,点击可调出菜单栏 */
Row {
spacing: 10
Rectangle {
width: 20
height: 20
radius: 10
color: "gray"
MouseArea {
anchors.fill: parent
onClicked: {
/* 触发“详情按钮”,动态调整菜单栏的位置 */
menu.x = getGlobalPosition(this).x this.width
menu.y = getGlobalPosition(this).y this.height
menu.visible = !menu.visible
}
}
}
Text {
text: "detail"
}
}
}
}
}
/* 获取相对于根窗口的全局的坐标,输入参数为需要获取全局坐标的对象 */
function getGlobalPosition(targetObject) {
var positionX = 0
var positionY = 0
var obj = targetObject
/* 遍历所有的父窗口 */
while (obj != null) {
/* 累加计算坐标 */
positionX = obj.x
positionY = obj.y
obj = obj.parent
}
return {"x": positionX, "y": positionY}
}
/* 菜单栏 */
Rectangle {
id: menu
visible: false
width: 90
height: 90
border.width: 1
border.color: "#d5d5d5"
ListView {
id: listView
width: menu.width - 2
height: menu.height -2
anchors.centerIn: parent
interactive: false
model: ["Title1", "Title2", "Title2"]
delegate:
Rectangle {
width: listView.width
height: listView.height / 3
color: mouseArea.pressed || mouseArea.isEntered ? "#0078d8" : "white"
MouseArea {
id: mouseArea
property bool isEntered: false
anchors.fill: parent
hoverEnabled: true
onEntered: isEntered = true
onExited: isEntered = false
onClicked: menu.visible = false
}
Text {
anchors.centerIn: parent
text: modelData
color: mouseArea.pressed || mouseArea.isEntered ? "white" : "black"
}
Rectangle {
visible: index !== 0
width: menu.width
height: 1
color: menu.border.color
}
}
}
}
}