Delegates QML-自定义PageIndicator以显示其指示的每个页面的图像

Delegates QML-自定义PageIndicator以显示其指示的每个页面的图像,delegates,qml,customization,Delegates,Qml,Customization,更新:为SwipeView添加了代码 我正试图定制页面指示器来完成我目前有三个按钮的任务 通过点击PageIndicator内的相应项目,可以更改页面(目前我有3个页面,每页一个按钮,点击onClicked可将SwipeView更改为预定义索引-否PageIndicator) 显示每个页面指示器项目的自定义图像(目前我有3个页面,每页一个按钮,带有自定义图像-无PageIndicator) MySwipeView具有以下结构: SwipeView { id: detailsView

更新:
SwipeView添加了代码

我正试图定制
页面指示器
来完成我目前有三个按钮的任务

  • 通过点击
    PageIndicator
    内的相应项目,可以更改页面(目前我有3个页面,每页一个按钮,点击
    onClicked
    可将
    SwipeView
    更改为预定义索引-否
    PageIndicator
  • 显示每个页面指示器项目的自定义图像(目前我有3个页面,每页一个按钮,带有自定义图像-无
    PageIndicator
My
SwipeView
具有以下结构:

SwipeView {
    id: detailsView
    Layout.fillWidth: true
    Layout.preferredHeight: layoutTopLevel.height * .9
    Page {
        id: captureViewPage
        header: Text {
            text: "Capture view"
            horizontalAlignment: Text.AlignHCenter
            font.pixelSize: 20
        }
    }
    Page {
        id: helpViewPage
        header: Text {
            text: "Help view"
            horizontalAlignment: Text.AlignHCenter
            font.pixelSize: 20
        }

        footer: TabBar {
            id: helpViewSubCategories
            currentIndex: 0
            TabButton {
                text: qsTr("Gestures")
            }
            TabButton {
                text: qsTr("General")
            }
        }
    }
    Page {
        id: settingsViewPage
        header: Text {
            text: "Settings view"
            horizontalAlignment: Text.AlignHCenter
            font.pixelSize: 20
        }

        footer: TabBar {
            id: settingsViewSubCategories
            currentIndex: 0
            TabButton {
                text: qsTr("Language")
            }
            TabButton {
                text: qsTr("Device")
            }
        }
    }
}
SwipeView
PageIndicator
(见下文)都是
列布局的一部分,是子列:

ColumnLayout {
        id: layoutDetailsAndMenu
        spacing: 0
        SwipeView { ... }
        PageIndicator { ... }
}
首先,我研究了
PageIndicator
delegate
属性是如何工作的。例如,下面的QML代码

    PageIndicator {
            id: detailsViewIndicator
            count: detailsView.count
            currentIndex: detailsView.currentIndex
            interactive: true
            anchors.bottom: detailsView.bottom
            anchors.bottomMargin: -40
            anchors.horizontalCenter: parent.horizontalCenter


            delegate: Rectangle {
                    implicitWidth: 15
                    implicitHeight: 15

                    radius: width
                    color: "#21be2b"

                    opacity: index === detailsView.currentIndex ? 0.95 : pressed ? 0.7 : 0.45

                    Behavior on opacity {
                        OpacityAnimator {
                            duration: 100
                        }
                    }
                }
        }
生成以下绿色结果:


通过单击
页面指示器中的相应项目,可以更改页面

由于某种原因,
非活动
根本不起作用。我将引用文档说明此属性的功能:

交互式:bool

此属性保存控件是否是交互式的。互动的 页面指示器对按下按钮做出反应并自动更改当前页面 适当索引。默认值为false

我不知道这是一个bug还是我遗漏了什么,但即使没有通过
委托
进行自定义,单击页面指示器项目也不会改变当前页面(这些项目的数量与页面数量相等,因此单击没有为其分配页面的索引是毫无疑问的)

因此,为了实现我的第一个愿望,我添加了一个
MouseArea

    PageIndicator {
            // ...
            delegate: Rectangle {
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        if(index !== detailsView.currentIndex) {
                            detailsView.setCurrentIndex(index);
                        }
                    }
                }
            }
    }
正如您所看到的,我正在使用
onClicked
事件处理程序(或任何这些东西的调用),并检查
PageIndicator
的当前索引是否等于我的
SwipeView
中的页面。如果不是这种情况,我使用
setCurrentIndex(index)
将我的
SwipeView
设置为所选索引

在我写了这篇文章之后,我非常满意它按照我的设想工作(尽管
交互式
的事情仍然困扰着我)。下一步是添加图像


显示每个页面指示器项目的自定义图像

首先,让我向您展示我希望事情看起来如何(这实际上是最终结果,但更多的是-稍后):

注意:我使用了我没有的
Qt
徽标。用于演示目的

从左到右,
QRC
URL是:

  • qrc:/icons/qtlogo.png

  • qrc:/icons/qtlogo1.png

  • qrc:/icons/qtlogo2.png

其来源如下:

            delegate: Image {
                source: detailsViewIndicator.indicatorIcons[detailsView.currentIndex]
                height: 30
                width: 30
                opacity: index === detailsView.currentIndex ? 0.95 : pressed ? 0.7 : 0.45
                MouseArea {
                    anchors.fill: parent
                    onClicked: {
                        if(index !== detailsView.currentIndex) {
                            detailsView.setCurrentIndex(index);
                            source = detailsViewIndicator.indicatorIcons[detailsView.currentIndex];
                        }
                    }
                }
            }
其中
指示符
是my
页面指示符的
变体
属性

    property variant indicatorIcons: [
                "qrc:/icons/qtlogo.png",
                "qrc:/icons/qtlogo1.png",
                "qrc:/icons/qtlogo2.png"
            ]
我已经为
QRC
url使用了
string
对象数组,因为这似乎是不可能的

delegate: detailsViewIndicator.indicatorImages[detailsView.currentIndex]
带有
指示符号的图像

property list<Image> indicatorImages: [
  Image { source: "..." },
  Image { source: "..." },
  Image { source: "..." }
]
第一次运行应用程序时,我得到:

这是因为最初选择的索引是
0
,因此生成了带有
源代码的
图像
:“qrc:/icons/qtlogo.png”
,所有页面指示器项目都用它填充。如果我选择另外两个页面中的一个作为最初选择的页面,我将分别获得
qrc:/icons/qtlog1.png
qrc:/icons/qtlog2.png

SwipeView
点击
页面指示器
)中滑动会导致

这仅在一个方向上(从左到右按索引)。如果我倒退,我会得到相同的结果,但顺序相反

点击会让事情变得更有趣。在下面的屏幕截图中,我在初始化后单击了第二个页面指示项(带有
qrc:/icons/qtlogo1.png
作为
图像的源):

接下来,我单击了第三页的指示项:

再次点击后,我得到:

显然,事情不是这样的。我希望从开始到结束都能得到最终结果,无论哪个页面被刷走或页面指示器项目被点击

有人做过这样的事吗?这可能吗

由于某种原因,非活动的根本不起作用

我假设这是一个输入错误,因为使用
交互式
属性对我有效(Qt5.7):

与第一个示例的简化版本一样:

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true

    PageIndicator {
        id: detailsViewIndicator
        count: 3
        currentIndex: 0
        interactive: true

        delegate: Rectangle {
            implicitWidth: 15
            implicitHeight: 15

            radius: width
            color: "#21be2b"

            opacity: index === detailsViewIndicator.currentIndex ? 0.95 : pressed ? 0.7 : 0.45

            Behavior on opacity {
                OpacityAnimator {
                    duration: 100
                }
            }
        }
    }
}
因此,如果
SwipeView
没有改变页面,那么问题很可能就在那里,我们需要查看该代码

我希望从开始到结束都能得到最终结果,无论哪个页面被刷走或页面指示器项目被点击

我认为问题在于您用于图标数组的索引:

source: detailsViewIndicator.indicatorIcons[detailsView.currentIndex]
这将使用当前选定的索引,而您似乎希望使用该代理的索引:

source: detailsViewIndicator.indicatorIcons[index]
顺便说一下,指定图标源的一种更简单的方法是使用字符串连接(并为文件提供适当的名称以匹配):


在您添加的代码中,
SwipeView
不会将其
currentIndex
设置为
PageIndicator
currentIndex
。您可以这样做:

currentIndex: detailsViewIndicator.currentIndex
完整示例:

import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        SwipeView {
            id: detailsView
            currentIndex: detailsViewIndicator.currentIndex
            Layout.fillWidth: true
            Layout.fillHeight: true

            Page {
                id: captureViewPage
                header: Text {
                    text: "Capture view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }
            }
            Page {
                id: helpViewPage
                header: Text {
                    text: "Help view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }

                footer: TabBar {
                    id: helpViewSubCategories
                    currentIndex: 0
                    TabButton {
                        text: qsTr("Gestures")
                    }
                    TabButton {
                        text: qsTr("General")
                    }
                }
            }
            Page {
                id: settingsViewPage
                header: Text {
                    text: "Settings view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }

                footer: TabBar {
                    id: settingsViewSubCategories
                    currentIndex: 0
                    TabButton {
                        text: qsTr("Language")
                    }
                    TabButton {
                        text: qsTr("Device")
                    }
                }
            }
        }

        PageIndicator {
            id: detailsViewIndicator
            count: detailsView.count
            currentIndex: detailsView.currentIndex
            interactive: true
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
}
另一个注意事项:使用垂直锚(
anchors.bottomsource: "qrc:/icons/qtlogo" + index + ".png"
currentIndex: detailsViewIndicator.currentIndex
import QtQuick 2.5
import QtQuick.Layouts 1.1
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true
    width: 640
    height: 480
    title: qsTr("Hello World")

    ColumnLayout {
        anchors.fill: parent

        SwipeView {
            id: detailsView
            currentIndex: detailsViewIndicator.currentIndex
            Layout.fillWidth: true
            Layout.fillHeight: true

            Page {
                id: captureViewPage
                header: Text {
                    text: "Capture view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }
            }
            Page {
                id: helpViewPage
                header: Text {
                    text: "Help view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }

                footer: TabBar {
                    id: helpViewSubCategories
                    currentIndex: 0
                    TabButton {
                        text: qsTr("Gestures")
                    }
                    TabButton {
                        text: qsTr("General")
                    }
                }
            }
            Page {
                id: settingsViewPage
                header: Text {
                    text: "Settings view"
                    horizontalAlignment: Text.AlignHCenter
                    font.pixelSize: 20
                }

                footer: TabBar {
                    id: settingsViewSubCategories
                    currentIndex: 0
                    TabButton {
                        text: qsTr("Language")
                    }
                    TabButton {
                        text: qsTr("Device")
                    }
                }
            }
        }

        PageIndicator {
            id: detailsViewIndicator
            count: detailsView.count
            currentIndex: detailsView.currentIndex
            interactive: true
            anchors.horizontalCenter: parent.horizontalCenter
        }
    }
}