从QML ListView获取焦点/活动焦点状态

从QML ListView获取焦点/活动焦点状态,listview,qt4,focus,qml,qt-quick,Listview,Qt4,Focus,Qml,Qt Quick,我有一个两列布局,在左列有一个ListView。使用左/右键,我可以在应用程序的两个部分之间切换焦点 左列的活动焦点被委托给ListView,并从那里直接委托给它的一行 如何检查ListView或其子项是否具有焦点 import QtQuick 1.1 FocusScope { width: 960 height: 540 id: app focus: true FocusScope { id: leftColumn K

我有一个两列布局,在左列有一个ListView。使用左/右键,我可以在应用程序的两个部分之间切换焦点

左列的活动焦点被委托给ListView,并从那里直接委托给它的一行

如何检查ListView或其子项是否具有焦点

import QtQuick 1.1

FocusScope {
    width: 960
    height: 540
    id: app
    focus: true

    FocusScope {
        id: leftColumn
        KeyNavigation.right: rightColumn
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.top: parent.top
        width: 250
        focus: true

        Rectangle {
            id: leftBackgroundColor
            anchors.fill: parent
            color: contactsList.activeFocus ? "red" : "#E6E6E6"

            ListView {
                id: contactsList
                interactive: true
                anchors.fill: parent
                focus: true

                delegate: Text {
                    text: name
                    font.bold: activeFocus
                }
                model: ListModel {
                    ListElement { name: "Simon" }
                    ListElement { name: "Mary" }
                    ListElement { name: "Jack" }
                    ListElement { name: "Frank" }
                }

            }
        }
     }


    FocusScope {
        id: rightColumn
        KeyNavigation.left: leftColumn

        anchors.left: leftColumn.right
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.top: parent.top
        onFocusChanged: console.log("Right focus changed: " + focus + "/" + activeFocus)

        Rectangle {
            id: rightBackgroundColor
            anchors.fill: parent
            focus: true
            color: activeFocus ? "red" : "#b3b3b3"            
        }
    }
}

在这段代码中,您正在为自己制造麻烦。在任何给定的时间,只有一个元素可以具有焦点,因此如果将每个元素的focus属性设置为true,则在渲染时,并不特别清楚哪个元素具有焦点(我相信这是渲染的最后一个具有焦点集的元素)。至于找出哪个元素有焦点,你不能请求当前的焦点元素。您可以将侦听器连接到元素上存在的onFocusChanged事件,以便在对象获得/失去焦点时执行操作。一个更好的问题可能是为什么你关心谁有焦点?

我想我找到了一个解决办法:

import QtQuick 1.1

FocusScope {
    width: 960
    height: 540
    id: app
    focus: true

    FocusScope {
        id: leftColumn
        KeyNavigation.right: rightColumn
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.top: parent.top
        width: 250
        focus: true

        Rectangle {
            id: leftBackgroundColor
            anchors.fill: parent
            color: contactsList.activeFocus ? "red" : "#E6E6E6"

            ListView {
                id: contactsList
                interactive: true
                anchors.fill: parent
                focus: true

                delegate: Text {
                    text: name
                    font.bold: activeFocus
                }
                model: ListModel {
                    ListElement { name: "Simon" }
                    ListElement { name: "Mary" }
                    ListElement { name: "Jack" }
                    ListElement { name: "Frank" }
                }

            }
        }
     }


    FocusScope {
        id: rightColumn
        KeyNavigation.left: leftColumn

        anchors.left: leftColumn.right
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.top: parent.top
        onFocusChanged: console.log("Right focus changed: " + focus + "/" + activeFocus)

        Rectangle {
            id: rightBackgroundColor
            anchors.fill: parent
            focus: true
            color: activeFocus ? "red" : "#b3b3b3"            
        }
    }
}
onActiveFocusChanged: { focusChanged(focus) }
每当活动焦点改变时,它就会发出焦点改变信号。使用此选项,属性绑定(如color:parent.focus?“red”:“#e6”)也可以工作

完整测试代码:

import QtQuick 1.1

FocusScope {
    width: 960
    height: 540
    id: app
    focus: true

    FocusScope {
        id: leftColumn
        KeyNavigation.right: rightColumn
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.top: parent.top
        width: 250

        onActiveFocusChanged: { focusChanged(focus) }

        Rectangle {
            id: leftBackgroundColor
            anchors.fill: parent
            color: parent.focus ? "red" : "#E6E6E6"

            ListView {
                id: contactsList
                interactive: true
                anchors.fill: parent
                focus: true

                delegate: Text {
                    text: name
                    font.bold: activeFocus
                }
                model: ListModel {
                    ListElement { name: "Simon" }
                    ListElement { name: "Mary" }
                    ListElement { name: "Jack" }
                    ListElement { name: "Frank" }
                }

            }
        }
     }


    FocusScope {
        id: rightColumn
        focus: true
        KeyNavigation.left: leftColumn

        anchors.left: leftColumn.right
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.top: parent.top

        onActiveFocusChanged: { focusChanged(focus) }

        Rectangle {
            id: rightBackgroundColor
            anchors.fill: parent
            focus: true
            color: activeFocus ? "red" : "#b3b3b3"            
        }
    }
}

我知道这是一个老生常谈的问题,但我认为它仍然值得一个恰当的解释,因为同样的焦点模型仍然在QTQuick2中使用

如何检查ListView或其子项是否具有焦点

import QtQuick 1.1

FocusScope {
    width: 960
    height: 540
    id: app
    focus: true

    FocusScope {
        id: leftColumn
        KeyNavigation.right: rightColumn
        anchors.bottom: parent.bottom
        anchors.left: parent.left
        anchors.top: parent.top
        width: 250
        focus: true

        Rectangle {
            id: leftBackgroundColor
            anchors.fill: parent
            color: contactsList.activeFocus ? "red" : "#E6E6E6"

            ListView {
                id: contactsList
                interactive: true
                anchors.fill: parent
                focus: true

                delegate: Text {
                    text: name
                    font.bold: activeFocus
                }
                model: ListModel {
                    ListElement { name: "Simon" }
                    ListElement { name: "Mary" }
                    ListElement { name: "Jack" }
                    ListElement { name: "Frank" }
                }

            }
        }
     }


    FocusScope {
        id: rightColumn
        KeyNavigation.left: leftColumn

        anchors.left: leftColumn.right
        anchors.right: parent.right
        anchors.bottom: parent.bottom
        anchors.top: parent.top
        onFocusChanged: console.log("Right focus changed: " + focus + "/" + activeFocus)

        Rectangle {
            id: rightBackgroundColor
            anchors.fill: parent
            focus: true
            color: activeFocus ? "red" : "#b3b3b3"            
        }
    }
}
这里的中心问题是,您似乎对两个焦点属性的含义有点困惑(这是可以理解的,有点不明显)

要查看聚焦镜(或其任何子项)是否立即具有焦点,您需要检查其上的
Item::activeFocus
属性。这意味着“要么我,要么我的一个孩子现在有焦点”,当焦点移到另一个聚焦镜时,它会从聚焦镜中递归清除

另一方面,
Item::focus
是对焦点的请求,而不是关于当前状态的信息,因此您不应该将其上的其他值(例如
color:foo.focus?“black”:“red”
)绑定到它,除非您想检查该项是否能够在将来的某个时间获得焦点,不是现在是否有焦点

这就解释了为什么你可以用
Item::focus
true来表示某些东西,而实际上它没有焦点——这不是信号丢失,而是你误用了属性来表示它没有

所以,你想要这样的东西:

Rectangle {
        id: leftBackgroundColor
        anchors.fill: parent
        color: leftColumn.activeFocus ? "red" : "#E6E6E6"
}

...

Rectangle {
    id: rightBackgroundColor
    anchors.fill: parent
    focus: true
    color: rightColumn.activeFocus ? "red" : "#b3b3b3"
}

在任何给定的时间,在每个FocusScrope中只有一个元素可以有焦点,这不是真的吗?我关心焦点,因为我想在任何一个左栏的子栏有焦点时立即更改整个左栏的背景色。实际上我不熟悉焦点镜元素,所以这是我的缺点。这个问题的答案似乎在于将子元素包装在聚焦镜中,并在父元素中创建一个绑定到聚焦镜焦点属性的属性,以更改其背景色。类似背景色的东西:focusScope.focus?“红色”:使用预设值的“蓝色”Jap。但看起来好像有一个bug,因为当我在两列之间导航时,focus属性没有改变,也没有在leftColumn或rightColumn上调用onFocusChanged函数。我对调用信号有点谨慎,但这确实解决了active focus没有触发信号的问题。这确实解决了我看到的渲染问题+1.