后台找gridview里面的控件id_Qml获取某个控件的全局坐标

源于一个Qml项目需求。需要在界面显示菜单栏,但菜单栏需要根据控件的所在位置显示。如下演示:

d9a9b20e012d20f5428ce4e6315d072c.gif

  点击详情(detail)按钮调出菜单列表。菜单栏的位置需要定位详情按钮的下面,那么就需要知道具体坐标。

  由于Qml控件的坐标是相对坐标(相对于父控件的坐标),既然是相对父控件的坐标,那么我们遍历所有父控件的坐标进行累加就可以计算出该控件的全局坐标了。

实现代码

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}
}

演示例子代码

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
                    }
                }
        }
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值