代码之家  ›  专栏  ›  技术社区  ›  karlphillip

更改模型后未正确绘制QML中继器

  •  0
  • karlphillip  · 技术社区  · 4 年前

    棕色的 a内的块 ColumnLayout Repeater

    我正在尝试更改 model 中继器 当用户单击屏幕以强制用户界面绘制不同数量的块时,会动态地执行此操作。每当通过更改所需的块数时 blockCount blockHeight ,每个块的高度,使更少的块可以占用屏幕上更多的空间。至少这是理论!

    出于调试目的,单击屏幕集 .

    右侧的当前结果 :

    如上图所示,当点击发生时 rectId.blockCount = 2 执行时,它似乎会触发一系列调用:

    • 中继器 之前 重新计算;
    • 或者 anchors 列布局

    我试图理解是什么导致了这种行为,同时也在寻找一种方法,允许应用程序动态更改块的数量,同时能够正确地绘制它们!

    我错过了什么?

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Layouts 1.15
    
    Window {
        id: wndId
        property int wndWidth: 200
        property int wndHeight: 300
    
        visible: true
        width: wndWidth
        height: wndHeight
        title: qsTr("Testing ColumnLayout")
    
        Rectangle {
            id: rectId
    
            property int borderWidth: 5  // width of the blue frame surrounding the window
            property int blockCount: 4   // number of blocks to be drawn using Repeater
            property int blocksSpace: 8  // minimum space between the blocks
    
            width: wndId.wndWidth
            height: wndId.wndHeight
            border.color: "blue"
            border.width: borderWidth
    
            // size of each inner rectangle is computed dinamically: changing blockCount should update blockHeight
            property int blockWidth: rectId.width - (rectId.borderWidth * 4)
            property int blockHeight: updateBlockHeight()
    
            function updateBlockHeight(numBlocks)
            {
                if (numBlocks === undefined)
                    numBlocks = rectId.blockCount;
    
                var newHeight = (rectId.height - ((rectId.borderWidth + rectId.blocksSpace)*2) - (rectId.blocksSpace * (numBlocks-1))) / numBlocks;
                print("updateBlockHeight: newHeight=", newHeight);
                return newHeight;
            }
    
            Component.onCompleted: print("Outter Rectangle w=" + rectId.width + " h=" + rectId.height)
    
            // draw blocks on top of each other with some space between them
            ColumnLayout {
                spacing: rectId.blocksSpace
                Layout.alignment: Qt.AlignBottom
                anchors.bottom: parent.bottom
                anchors.bottomMargin: rectId.borderWidth + rectId.blocksSpace
                anchors.left: rectId.left
                anchors.leftMargin: rectId.borderWidth*2
    
                Repeater {
                    id: repId
                    model: rectId.blockCount
    
                    // each block size is calculated dinamically
                    Rectangle {
                        id: blockId
                        color: "brown"
                        width: rectId.blockWidth
                        height: rectId.blockHeight
    
                        // Debug:
                        Component.onCompleted: {
                            print("Inner Rectangle")
                            print("  blockCount=" + rectId.blockCount);
                            print("  blockId.width=" + blockId.width + " blockId.height=" + blockId.height)
                            print("  blockWidth=" + rectId.blockWidth + " blockHeight=" + rectId.blockHeight)
                        }
    
                        Component.onDestruction: print("~Inner Rectangle")
    
                    } // inner Rectangle
    
                    Component.onCompleted: print("Repeater")
                    Component.onDestruction: print("~Repeater")
                } // Repeater
    
            } // ColumnLayout
    
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    print("Mouse clicked!");
    
                    // since repId uses blockCount as the model, any change to it should automatically recreate the elements of the Repeater
                    // here we force blockHeight to be recalculated before the model is changed
                    rectId.blockHeight = rectId.updateBlockHeight(2)
    
                    // and finally we change the number of blocks, forcing the Repeater to redraw the model correctly
                    rectId.blockCount = 2;
                    print("blockHeight= " + rectId.blockHeight);
                }
            }
    
        } // outter Rectangle
    
    } // Window
    
    
    0 回复  |  直到 4 年前
        1
  •  2
  •   Amfasis    4 年前

    你为什么要计算 blockHeight blockWidth ColumnLayout ?

    使用 Layout.fillWidth Layout.fillHeight 属性来表示 列布局 列布局 它将完成你试图自行编程的计算。

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Layouts 1.3
    
    Window {
        id: wndId
        property int wndWidth: 200
        property int wndHeight: 300
    
        visible: true
        width: wndWidth
        height: wndHeight
        title: qsTr("Testing ColumnLayout")
    
        Rectangle {
            id: rectId
    
            property int borderWidth: 5  // width of the blue frame surrounding the window
            property int blockCount: 4   // number of blocks to be drawn using Repeater
            property int blocksSpace: 8  // minimum space between the blocks
    
            width: wndId.wndWidth
            height: wndId.wndHeight
            border.color: "blue"
            border.width: borderWidth
    
            Component.onCompleted: print("Outter Rectangle w=" + rectId.width + " h=" + rectId.height)
    
            // draw blocks on top of each other with some space between them
            ColumnLayout {
                spacing: rectId.blocksSpace
                Layout.alignment: Qt.AlignBottom
    
                anchors.fill: parent
                anchors.margins: rectId.borderWidth * 2
    
                Repeater {
                    id: repId
                    model: rectId.blockCount
    
                    // each block size is calculated dinamically
                    Rectangle {
                        id: blockId
                        color: "brown"
                        Layout.fillWidth: true
                        Layout.fillHeight: true
    
                        // Debug:
                        Component.onCompleted: {
                            print("Inner Rectangle", index)
                            print("  blockCount=" + rectId.blockCount);
                            print("  blockId.width=" + blockId.width + " blockId.height=" + blockId.height)
                            print("  blockWidth=" + rectId.blockWidth + " blockHeight=" + rectId.blockHeight)
                        }
    
                        Component.onDestruction: print("~Inner Rectangle")
    
                    } // inner Rectangle
    
                    Component.onCompleted: print("Repeater")
                    Component.onDestruction: print("~Repeater")
                } // Repeater
    
            } // ColumnLayout
    
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    print("Mouse clicked!");
    
                    // and finally we change the number of blocks, forcing the Repeater to redraw the model correctly
                    rectId.blockCount = 2;
                    print("blockHeight= " + rectId.blockHeight);
                }
            }
    
        } // outter Rectangle
    
    } // Window
    

    为了保存 方块高度

    如果你坚持保持计算,因为在现实世界中它更难(足够公平),我建议使用 implicitHeight implicitWidth 。这是因为布局引擎不会触发宽度/高度的更改,因为它应该自己设置这些值,但它会监视隐式大小:

    import QtQuick 2.12
    import QtQuick.Window 2.12
    import QtQuick.Layouts 1.3
    
    Window {
        id: wndId
        property int wndWidth: 200
        property int wndHeight: 300
    
        visible: true
        width: wndWidth
        height: wndHeight
        title: qsTr("Testing ColumnLayout")
    
        Rectangle {
            id: rectId
    
            property int borderWidth: 5  // width of the blue frame surrounding the window
            property int blockCount: 4   // number of blocks to be drawn using Repeater
            property int blocksSpace: 8  // minimum space between the blocks
    
            width: wndId.wndWidth
            height: wndId.wndHeight
            border.color: "blue"
            border.width: borderWidth
    
            // size of each inner rectangle is computed dinamically: changing blockCount should update blockHeight
            property int blockWidth: rectId.width - (rectId.borderWidth * 4)
            property int blockHeight: updateBlockHeight()
    
            function updateBlockHeight(numBlocks)
            {
                var newHeight = (rectId.height - ((rectId.borderWidth + rectId.blocksSpace)*2) - (rectId.blocksSpace * (rectId.blockCount-1))) / rectId.blockCount;
                print("updateBlockHeight: newHeight=", newHeight);
                return newHeight;
            }
    
            Component.onCompleted: print("Outter Rectangle w=" + rectId.width + " h=" + rectId.height)
    
            // draw blocks on top of each other with some space between them
            ColumnLayout {
                spacing: rectId.blocksSpace
                Layout.alignment: Qt.AlignBottom
                anchors.fill: parent
                anchors.margins: rectId.borderWidth * 2
    
                Repeater {
                    id: repId
                    model: rectId.blockCount
    
                    // each block size is calculated dinamically
                    Rectangle {
                        id: blockId
                        color: "brown"
                        implicitWidth: rectId.blockWidth
                        implicitHeight: rectId.blockHeight
                        onXChanged: print("x[",index,"]=", x)
                        onYChanged: print("y[",index,"]=", y)
    
                        // Debug:
                        Component.onCompleted: {
                            print("Inner Rectangle", index)
                            print("  blockCount=" + rectId.blockCount);
                            print("  blockId.width=" + blockId.width + " blockId.height=" + blockId.height)
                            print("  blockWidth=" + rectId.blockWidth + " blockHeight=" + rectId.blockHeight)
                        }
    
                        Component.onDestruction: print("~Inner Rectangle")
    
                    } // inner Rectangle
    
                    Component.onCompleted: print("Repeater")
                    Component.onDestruction: print("~Repeater")
                } // Repeater
    
            } // ColumnLayout
    
            MouseArea {
                anchors.fill: parent
                onClicked: {
                    print("Mouse clicked!");
    
                    // and finally we change the number of blocks, forcing the Repeater to redraw the model correctly
                    rectId.blockCount = 2;
                    print("blockHeight= " + rectId.blockHeight);
                }
            }
    
        } // outter Rectangle
    
    } // Window
    

    updateBlockHeight

        2
  •  1
  •   eyllanesc Yonghwan Shin    4 年前

    (来自我的评论)

    在Linux上使用Qt 5.15.1可以获得预期的输出。使用Qt 5.15,获取您指示的输出,以确定Qt 5.15.1中可能已修复的错误。