Qml获取某个控件的全局坐标

2023-03-17 14:20:30 浏览数 (3)

源于一个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
                    }
                }
        }
    }
}

1 人点赞