Trying using FocusScope in a simple QML project



  • Hi,
    Please take a look at this project. I've defined TLineEditV2.qml like that example and main.qml like this:

    import QtQuick 2.6
    import QtQuick.Window 2.2
    
    Window {
        visible: true
        width: 640
        height: 480
        title: qsTr("Text Input mian.qml")
    
        Rectangle {
     
            TLineEditV2 {
              id: input1
              text: "First"
             }
    
            TLineEditV2 {
               y: 100
               id: input2
               text: "Second"
            }
         }
     }
    

    This is my project's output: (!!)
    0_1507970852779_Capture.PNG

    Well, the book is one of the worst books I've ever seen.

    My comprehension:

    When we instantiate one object with the text "First" in main.qml, the program goes to TLineEditV2.qml.

    In the FocusScope:
    width: 96; height: input.height + 8, means that scope covers an area of width 96 and height of the TextInput's height property plus 8. Since the TextInput (with the id: input) doesn't have a height property explicilty declared, the default size is set.

    In the Rectangle {anchors.fill: parent color: "lightsteelblue" border.color: "gray"}, there is a rectangle that fills its parent (FocusScope), and has a color and border color.

    The: property alias text: input.text; property alias input: input, says a text property can be used for the instances of TLineEditV2.qml and that text goes to the TextInput's text property. It has also an input property that equals the TextInput type. I don't understand this part!

    Then we have a TextInput which displays an editable line of text, like this:

    TextInput {
            id: input
            anchors.fill: parent
            anchors.margins: 4
            focus: true
        }
    

    First what is the usage of that input alias property for the instances of TLineEditV2 please?

    Why is the output that ugly?



  • @tomy said in Trying using FocusScope in a simple QML project:

    Since the TextInput (with the id: input) doesn't have a height property explicilty declared, the default size is set.

    Here you go wrong; TextInput has "anchors.fill: parent", i.e. it follows its parent's width and height. What is the expected result if the TextInput should change its height to fit the parent's height and the parent should change its height to the TextInput's height? It will be fixed with

    FocusScope {
        width: 96; height: input.implicitHeight + 8
    


  • @tomy

    First what is the usage of that input alias property for the instances of TLineEditV2 please?

    In this little example there's no use for it, I think. Basically it just gives a possibility to access the TextInput object inside TLineEditV2 after TLineEditV2 has been instantiated. Then you could use it in the right side of a binding or in javascript:

    TLineEditV2 {
              id: input1
              text: "First"
             }
    Text{
    y:50
    text: input1.input.displayText
    }
    

    The example program itself doesn't work as advertised yet. You have to add KeyNavigation.tab to the two input controls in your main.qml:

    TLineEditV2 {
              id: input1
              text: "First"
              KeyNavigation.tab: input2
             }
    

    etc. Yes, I agree, the book sucks...



  • Thank you very much for your replies.



  • @Eeli-K

    TextInput has "anchors.fill: parent", i.e. it follows its parent's width and height.

    But its parent is FocusScope which hasn't a height itself! How is it possible?

    What is the expected result if the TextInput should change its height to fit the parent's height and the parent should change its height to the TextInput's height?

    But TextInput hasn't a height (to change it) but it looks and gets its parent's coordinates! I didn't get your question.



  • @tomy The question was rhetorical. It was a cyclic dependency, it can't be solved, and leads to unpredictable results.

    To be more exact: the FocusScope here has y coordinate, the upper left corner. It's also the top line. But what is the FocusScope's bottom line? To know it we must know the height first. OK, let's look at the height of 'input' item (because of the binding "height: input.height + 8"). What is the height of that item? There is

    id: input
    anchors.fill: parent
    

    which means that the top line of 'input' is bind to the top line of its parent and the bottom line is bind to the bottom line of its parent. The 'height' property of 'input' can be calculated only after the top and bottom lines have been set because setting anchors overrides height and/or width. Do you now see the problem?

    The application worked without going to an infinite loop or crashing or even giving a warning. Possibly it means that there was some value for the 'height' property for 'input' to start with (maybe 0?), but it was arbitrary from our point of view, and the engine used that to calculate the FocusScope's height and finally 'input's top and bottom anchors. It just did the best it could but there still was illogical mutual dependency in the code.



  • @Eeli-K

    the FocusScope here has y coordinate
    the upper left corner.

    What y coordinate? I see width here only, which expands in the direction of the X coordinate. To me, it's only the top line, not a corner.

    Do you now see the problem?

    What I understood is that anchors should anchor the object to the target by coordinates. In our case neither has any height of itself so they likely only passes to each other (recursively) and it probably never ends (an infinite cycle).

    (maybe 0?)

    Yes, and it verifies my prior guess when I said a default value is set.

    still was illogical mutual dependency in the code.

    The process is clear now for me. When there is no value for setting, the default value is zero usually. I think I should expect it in other future topics of QML as well.

    One more subtle question: In the FocusScope when we use height: input.height, zero for height is set as we saw, but when using height: input.implicitHeight, it goes downwards the y axis like that implicitHeight is equal to some units in height, near 8 or 10! A little odd.



  • @tomy

    What y coordinate? I see width here only, which expands in the direction of the X coordinate. To me, it's only the top line, not a corner.

    Yes you're correct, I thought about x and y coordinates where y marks the top of an item. 'x' and 'y' are properties which mark the upper left corner. For an item y+height is the bottom line's y value in coordinate's y-axis. I hope this is correct :)

    You seem to understand the problem and solution correctly. But it's not odd at all. The only sensible default value for height and width properties for an item is 0 if nothing else has been set or calculated. In the end those property values always tell the real height and width of an item, not the values you may have set explicitly. The implicit size on the other hand stays the same after you have set it (see the docs for Item). It should be a natural sensible default size for that kind of item. What would be more sensible default height for a text element than the height of a text line? In the code above the FocusScope's height was set to "input.height + 8" which was 0+8 when it was calculated. But "input.implicitHeight + 8" was likely "TextInput's implicit height which is a text line's height based on font which was currently used"+8.



  • @Eeli-K

    What would be more sensible default height for a text element than the height of a text line? In the code above the FocusScope's height was set to "input.height + 8" which was 0+8 when it was calculated. But "input.implicitHeight + 8" was likely "TextInput's implicit height which is a text line's height based on font which was currently used"+8.

    Right.
    TLineEditV2 will be instantiated in main.qml so it would be better if it had implicit properties.
    Thanks.


Log in to reply
 

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