【问题标题】:Trying to center items programmatically in a ListView尝试以编程方式在 ListView 中居中项目
【发布时间】:2015-08-30 15:33:02
【问题描述】:

我想在 QML ListView 中有居中的项目,因此我添加了我的 ListView 的以下代码:

import QtQuick 2.0
import QtMultimedia 5.5
import QtQuick.Controls 1.3
import QtQuick.Extras 1.4
import QtQuick.Layouts 1.2
import QtQuick.Window 2.2
import QtTest 1.1

Rectangle {
    id: ueKeypad

    width: ueMainColumnLayout.implicitWidth+2*radius
    height: ueMainColumnLayout.implicitHeight+2*radius

    color: "grey"

    radius: 8

    border.color: "#99c6f0"
    border.width: 4

    ColumnLayout {
        id: ueMainColumnLayout

        anchors.fill: parent
        anchors.margins: radius

        spacing: 4

        RowLayout {
            id: ueTextLayout

            Text {
                id: ueStaffLoginText

                text: qsTr("Staff Login")

                verticalAlignment: Text.AlignVCenter
                horizontalAlignment: Text.AlignHCenter

                font.family: "Padauk"
                textFormat: Text.RichText

                font.pointSize: 16
                font.bold: true

                color: ueKeypad.border.color

                Layout.fillWidth: true
            }   // ueStaffLoginText
        }   // ueTextLayout

        RowLayout {
            id: uePeopleViewLayout

            ListView {
                id: uePeopleView

                keyNavigationWraps: true

                spacing: 4

                antialiasing: true

                model: uePeopleModel

                Layout.fillWidth: true
                Layout.fillHeight: false

                //Layout.minimumWidth: 64
                Layout.minimumHeight: 64
                //Layout.preferredWidth: 96
                Layout.preferredHeight: 96
                //Layout.maximumWidth: 128
                Layout.maximumHeight: 128

                orientation: ListView.Horizontal
                layoutDirection: Qt.LeftToRight

                snapMode: ListView.SnapToItem

                highlightRangeMode: ListView.ApplyRange

                Component.onCompleted: {
                    var newIndex=(count%2==0)?(count/2):(Math.round(count/2));

                    positionViewAtIndex(newIndex, ListView.Center);
                    currentIndex=newIndex;
                    print(newIndex)
                }   // onCompleted - center items

                delegate: Rectangle {
                        id: uePersonDelegate

                        width: 32
                        height: 32

                        ColumnLayout {
                            id: uePersonDelegateMainLayout

                            anchors.fill: parent
                            anchors.margins: radius

                            RowLayout {
                                id: uePersonDelegateImageLayout

                                Image {
                                    id: uePersonImage

                                    antialiasing: true

                                    fillMode: Image.PreserveAspectFit

                                    source: "image://uePeopleModel/"+model.ueRoleImage
                                }   // uePersonImage
                            }   // uePersonDelegateImageLayout

                            RowLayout {
                                id: uePersonDelegateNameLayout

                                Text {
                                    id: ueTextPersonName

                                    color: "#ffffff"

                                    text: model.ueRoleName

                                    font.bold: true
                                    font.pixelSize: 16

                                    verticalAlignment: Text.AlignVCenter
                                    horizontalAlignment: Text.AlignHCenter
                                }   // ueTextPersonName
                            }   // uePersonDelegateNameLayout
                        }   // uePersonDelegateMainLayout
                    }   // uePersonDelegate

                add: Transition {
                    NumberAnimation {
                        property: "opacity";
                        from: 0;
                        to: 1.0;
                        duration: 100
                    }   // NumberAnimation

                    NumberAnimation {
                        property: "scale";
                        from: 0;
                        to: 1.0;
                        duration: 100
                    }   // NumberAnimation
                }   // Transition

                displaced: Transition {
                    NumberAnimation {
                        properties: "x,y";
                        duration: 100;
                        easing.type: Easing.OutBounce
                    }   // NumberAnimation
                }   // Transition
            }   // uePeopleView
        }   // uePeopleViewLayout

        RowLayout {
            id: ueTumblerLayout

            Tumbler {
                id: ueLoginKeypadTumbler

                Layout.fillWidth: true
                Layout.fillHeight: false

                height: 100

                antialiasing: true

                TumblerColumn {
                    id: ueNumericTumblerColumnDigit1000

                    model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
                }   // ueNumericTumblerColumnDigit1000

                TumblerColumn {
                    id: ueNumericTumblerColumnDigit100

                    model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
                }   // ueNumericTumblerColumnDigit100

                TumblerColumn {
                    id: ueNumericTumblerColumnDigit10

                    model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
                }   // ueNumericTumblerColumnDigit10

                TumblerColumn {
                    id: ueNumericTumblerColumnDigit1

                    model: [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
                }   // ueNumericTumblerColumnDigit1
            }   // ueLoginKeypadTumbler
        }   // ueTumblerLayout

        RowLayout {
            id: ueButtonsLayout

            Button {
                id: ueButtonLogin

                Layout.fillWidth: true

                text: qsTr("Login")
            }   // ueButtonLogin

            Button {
                id: ueButtonClear

                Layout.fillWidth: true

                text: qsTr("Clear")
            }   // ueButtonClear

            Button {
                id: ueButtonQuitApp

                Layout.fillWidth: true

                text: qsTr("Quit")
            }   // ueButtonQuitApp
        }   // ueButtonsLayout
    } // ueMainColumnLayout

    states: [
        State {
            name: "ueStateLoginOk"

            PropertyChanges {
                target: ueKeypad
                border.color: "#00ff00"
            }

            PropertyChanges {
                target: ueLoginText
                color: "#00ff00"
            }
        },  // ueStateLoginOk

        State {
            name: "ueStateLoginOkFailed"

            PropertyChanges {
                target: ueKeypad
                border.color: "#ff0000"
            }

            PropertyChanges {
                target: ueLoginText
                color: "#ff0000"
            }
        }   // ueStateLoginOkFailed
    ]   // states
}   // ueKeypad

现在,print(newIndex) 语句打印出正确的值 3(在我的情况下,因为目前我有 5 个项目),我希望第三个项目位于 ListView 和其他两个项目的中心左侧和右侧的项目。这可能吗?并且超出了这个问题的范围,为什么Transitions 也不起作用,例如?

我还设置了 highlightRangeMode: ListView.ApplyRange 取自评论提示。

这是问题的截图:

【问题讨论】:

    标签: qt qml qtquick2 qtquickcontrols qtquickextras


    【解决方案1】:

    这里的问题是您试图根据您的需要放置ListView 代表。这是完全错误的,因为ListView(就像所有其他视图一样)旨在为您做到这一点,根据ListView 大小ListView始终使用所有可用空间,导致所有代表都位于左侧,如您所见。

    您应该限制ListView 的大小并将其放置在中心,而不是强制代理行为。然后,您可以利用highlightRangeModepreferredHighlightBeginpreferredHighlightEndthis answer 确保当前选定的Item 在列表的中心。此外,通过使用StrictlyEnforceRange,您可以强制选择的Item 保持始终在中心,这将导致IMO 更好地选择所需的Item

    以下是实现此方法的示例。为了简单起见,大小被硬编码,但可以很容易地参数化。如前所述,我通过设置突出显示策略走得更远。希望对您有所帮助。

    import QtQuick 2.4
    import QtQuick.Window 2.2
    import QtQuick.Layouts 1.1
    
    Window {
        id: win
        width: 300
        height: 300
        visible: true
    
        ColumnLayout {
            anchors.fill: parent
    
            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "blue"
            }
    
            ListView {
                Layout.alignment: Qt.AlignCenter
                Layout.minimumWidth: 30 * 5 + 40
                Layout.preferredHeight: 50
                clip: true
                spacing: 15
                model: 10
                orientation: ListView.Horizontal
                delegate: Item {
                    width: 30
                    height: 50
                    Rectangle{
                        anchors.centerIn: parent
                        color: parent.ListView.isCurrentItem ? "red" : "steelblue"
                        width: 30
                        height: 30
                        Text {
                            text: index
                            anchors.centerIn: parent
                        }
                        scale: parent.ListView.isCurrentItem ? 1.5 : 1
                        Behavior on scale { NumberAnimation { duration: 200 } }
                    }
                }
                preferredHighlightBegin: width / 2 - 15
                preferredHighlightEnd: width / 2 + 15
                highlightRangeMode: ListView.StrictlyEnforceRange
                Component.onCompleted: currentIndex = count / 2
            }
    
            Rectangle {
                Layout.fillWidth: true
                Layout.fillHeight: true
                color: "yellow"
            }
        }
    }
    

    【讨论】:

    • 这是否也适用于垂直ListView
    • @KernelPanic 它应该适应考虑高度而不是宽度,但基本步骤在那里。我认为您应该在 SO 上找到类似的东西(或者至少我记得给出了垂直输入的答案......但可能是错误的)。
    猜你喜欢
    • 1970-01-01
    • 2010-10-08
    • 2010-11-07
    • 1970-01-01
    • 2019-12-17
    • 2011-08-13
    • 2016-04-27
    • 1970-01-01
    • 2013-12-25
    相关资源
    最近更新 更多