[Solved] Focus, child items, and the end of my wits



  • Hey guys,

    I've got an example here where I'm trying to find the "best" way to do this. I've got a QML window with 2 elements: a text box and a listview. You guessed it, it's a search window.

    I can easily assign focus programatically to 'scope' by setting scope.focus = true. The problem occurs when I try and figure out a decent way for setting the right focus when clicking on an element in the listview. The only way I can think of this happening in the delegate is by doing some parent.parent.parent.parent gibberish but that is very fragile as it depends on the hierarchy and I'm trying to create a re-usable ListView for my app.

    Can anyone think of a pattern that would help me accomplish what I'm trying to do here?

    Thanks!

    @
    import QtQuick 2.1
    import QtQuick.Controls 1.0
    import QtQuick.Layouts 1.0
    import QtGraphicalEffects 1.0

    ApplicationWindow {
    width: 600
    height: 300

    id: win
    
    ColumnLayout {
        anchors.fill: parent
    
        Text {
            Layout.fillWidth: true
            text: scope.focus ? "ListView has focus" : "ListView doesn't have focus"
        }
    
        TextInput {
            Layout.fillWidth: true
            focus: true
        }
    
        /* This is defined somewhere else, independent of the focus scope below */
        Component {
            id: myDelegate
            Text {
                text: modelData ? modelData.name + ' (' + modelData.age + ')' : ''
                width: parent ? parent.width : 0
                height: 32
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        /* how best to set the rectangle enclosing the focus scope to have
                           focus? */
                        /* This is the effect I want, but without referring to "scope" directly */
                        /* scope.focus = true */
                        /* Another way */
                        var scopehack = parent.parent.parent.parent.parent.parent.parent.parent.parent.parent
                        console.log(scope,scopehack)
                        scopehack.focus = true
                    }
                }
            }
        }
    
        /* Actually a Flipable */
        Rectangle {
    
            id: theflipable
            color: "#AABBCCDD"
            Layout.fillWidth: true
            Layout.fillHeight: true
    
            FocusScope {
                id: scope
                anchors.fill: parent
                focus: true
    
                Rectangle {
                    anchors.fill: parent
                    color: "transparent"
                    radius: 3
    
    
                    RectangularGlow {
                        anchors.fill: parent
                        visible: scope.activeFocus
                        glowRadius: 10
                        spread: 0.2
                        color: "red"
                        cornerRadius: 13
                    }
    
                    ScrollView {
                        anchors.fill: parent
                        /* The following two properties allow us to use keyboard navigation
                           within the ListView. See
                           https://bugreports.qt-project.org/browse/QTBUG-31976
                           */
                        flickableItem.interactive: true
                        focus: true
    
                        ListView {
                            anchors.fill: parent
                            boundsBehavior: Flickable.StopAtBounds
                            clip: true
                            focus: true
                            model: ListModel{}
                            delegate: Loader {
                                width: parent.width
                                sourceComponent: myDelegate
                                property variant modelData: model
                            }
    
                            highlightFollowsCurrentItem: true
                            highlight: Rectangle {
                                width: parent ? parent.width : 0
                                color: "#3465A4"
                            }
                            highlightMoveDuration: 250
    
                            Component.onCompleted: {
                                for(var ii = 0; ii < 250; ++ii) {
                                    model.append({'age':ii,'name':'Bopinder ' + ii})
                                }
                            }
                        }
                    }
                }
            }
        }
    }
    

    }
    @



  • what is the problem with setting the focus via id.focus = true or id.forceActiveFocus()? I don't understand why you don't like that, still better than parent.parent.parent.parent.parent.focus = true I guess :D

    Edit: if you don't know the item id at that point why not setting it from the outside to a custom property or something?
    @
    property Item focusTarget
    @
    and than from outside just set it to some id you want to get focus when you click on the delegate
    @
    yourComp.focusTarget = scope
    @



  • Because the problem I have is something like this:

    @
    MyTopLevelWindow {
    ColumnLayout {
    SearchBar {}
    RectangularGlow{...visible: searchResults.activeFocus }
    SearchResults{ id: searchResults}
    }
    @

    The actual ListView is way down, deep somewhere in the guts of SearchResults because I have a particular implementation I want to use. The focus is assigned to that but the rectangular glow effect is on the searchResults container. Does that make sense?



  • It looks like ListView.forceActiveFocus does what I need. Gonna do some testing.



  • see my edit, maybe that helps or I still don't know what the problem is the Item ids are usually accessible from everywhere unless its a separate qml file but then you can simple use an property alias or what i suggested maybe?



  • The key points to getting this was:

    Understanding that FocusScope is a chain going up ancestry

    I needed to was to forceActiveFocus on the child I wanted to get the active focus so it would bubble up to the parent that eventually had the RectangularGlow attached. Simply setting child.focus = true was not sufficient.

    Thanks for the quick help Xander84!


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.