Bootstrap

QML界面控件加载与显示顺序

一、QML界面控件加载顺序

QML在界面加载时的顺序和我们认知的有很大的不同,有时候会对我们获取参数以及界面实现造成很大的困扰

1、加载顺序

import QtQuick 2.12
import QtQml 2.12
import QtQuick.Window 2.12
import QtQuick.VirtualKeyboard 2.4
 
Window {
    id: window
    width: 800
    height: 480
    visible: true
    title: qsTr("Hello World")
    Component.onCompleted:
    {
        console.log("Window success")                       // 2
    }
    
    Item {
        Component.onCompleted:
        {
            console.log("Item success")                     // 7
        }
    }
    Rectangle
    {
        anchors.fill: parent
        color: "red"
        Row
        {
            Repeater
            {
                model: 3
                Text {
                    width: 100
                    height: 50
                    font.pixelSize: 30
                    color: "blue"
                    horizontalAlignment: Text.AlignHCenter
                    verticalAlignment: Text.AlignVCenter
                    text: qsTr("text")
                    Component.onCompleted:
                    {
                        console.log("text success")             // 1
                    }
                }
                Component.onCompleted:
                {
                    console.log("Repeater success")              // 6
                }
            }
            Component.onCompleted:
            {
                console.log("Row success")                        // 5
            }
        }
        Component.onCompleted:
        {
            console.log("Rectangle success")                      // 4
        }
    }
 
    InputPanel {
        id: inputPanel
        z: 99
        x: 0
        y: window.height
        width: window.width
 
        states: State {
            name: "visible"
            when: inputPanel.active
            PropertyChanges {
                target: inputPanel
                y: window.height - inputPanel.height
            }
        }
        transitions: Transition {
            from: ""
            to: "visible"
            reversible: true
            ParallelAnimation {
                NumberAnimation {
                    properties: "y"
                    duration: 250
                    easing.type: Easing.InOutQuad
                }
            }
        }
        Component.onCompleted:
        {
            console.log("InputPanel success")                     // 3
        }
    }
}

运行上面代码后调试信息如下:

总结:

除C++模块外,先是加载界面内的Repeater中重复的内容!!!!

再加载界面本身

然后按照从下到上,由外到内的加载,但是界面展示的顺序是由上到下!!!!

(信号的改变以及loader需要加载的都是优先加载的)

信号的改变高于界面本身的加载

2、影响

由于Repeater中重复的控件是最先被加载的,所以如果在加载的时候给控件赋初值,而这个值又是从C++端获取的参数,这时能否赋值成功取决于从C++获取参数的方式,如下第一种方式可以,第二种就会有问题

(1)导入c++的Object模块,实例化类对象,参数(类成员变量)在类的定义中使用 Q_PROPERTY 声明过。qml在任何时候调用被Q_PROPERTY宏修饰过参数都是不影响的

例1:

类定义:

Q_PROPERTY(int sampMode READ getSampMode WRITE setSampMode NOTIFY paraChanged)
Q_PROPERTY(int offerMode READ getOfferMode WRITE setOfferMode NOTIFY paraChanged)

例2:

(2)通过函数等方法传递 的参数就要注意了,函数调用的时机就尤为重要,必须在控件加载前调用!!!如下:

  • C++返回一个QVariantList类型的值给到qml端

  • Qml导入模块调用函数获取返回值

  • 根据加载顺序,这个时候在加载repeater的时候如果调用返回值的话,就会调用失败

但如果将 通过函数获取的C++参数绑定到一个变量上,qml通过变量来获取C++参数的话,也是可以的。如下:

二、QML界面显示顺序

qml会先将界面中的控件加载完成再显示,加载的顺序并不是界面的显示顺序,界面显示的顺序是由上到下的!!! 如下代码,实现一个点击编辑框后弹出键盘,同时整个界面整体往上推,将编辑框显示在键盘外面,以至不被键盘隐藏住

子界面会先显示出来,title后显示,当然人眼肯定是看不出来显示顺序的。如果想实现点击编辑框,弹出键盘,同时将子界面往上移,但又不能超过title的功能,就需要将title放置在子界面的下面或将title的z调高,因为键盘往上推的时候,实际是改变了子界面的y,那么在改变后重新显示的时候,如果title与子界面有了重叠,按照显示顺序,title要是在上面就会被子界面覆盖掉(看着是被一起往上推了,实则是被覆盖住了)

;