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

时间:2016-07-22 06:58:31

标签: delegates qml customization

更新:添加了SwipeView

的代码

我正在尝试自定义PageIndicator以执行我目前有三个按钮的操作

  • 点击PageIndicator内的相应项目即可更改页面(目前我有3个页面,每页一个按钮,onClicked设置为将SwipeView更改为预定义索引 - 没有PageIndicator
  • 显示每个页面指示器项目的自定义图像(目前我有3个页面,每页一个按钮带有自定义图像 - 没有PageIndicator

我的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")
            }
        }
    }
}

SwipeViewPageIndicator(见下文)都是ColumnLayout的一部分,并且属于下属:

ColumnLayout {
        id: layoutDetailsAndMenu
        spacing: 0
        SwipeView { ... }
        PageIndicator { ... }
}

首先,我研究了delegate的{​​{1}}属性是如何工作的。例如,以下QML代码

PageIndicator

产生以下绿色结果:

enter image description here

通过点击 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 } } } }

中的相应项目,可以更改页面

由于某种原因,PageIndicator根本不起作用。我将在文档中引用该属性应该执行的操作:

  

互动 bool

     

此属性保存控件是否是交互式的。互动   页面指​​示器响应按下并自动改变电流   指数恰当。默认值为 false

我不知道这是一个错误还是我错过了什么,但即使没有通过inactive点击页面指示项进行自定义,也会更改当前页面(这些项目的数量确实等于页面数量,因此单击没有分配页面的索引是不可能的。)

因此,为了让我的第一个愿望成真,我添加了delegate

MouseArea

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

在我写完这篇文章之后,我非常满意它按照我设想的方式工作(尽管SwipeView仍然困扰着我)。接下来是添加图像......

显示每个网页指标项的自定义图片

首先让我告诉你我喜欢看的东西(这实际上是最后的结果,但更多的是 - 后来就行了):

注意:我使用了我不拥有的interactive徽标。这是出于演示目的

enter image description here

从左到右,Qt网址为:

  • QRC

    enter image description here

  • qrc:/icons/qtlogo.png

    enter image description here

  • qrc:/icons/qtlogo1.png

    enter image description here

其来源如下:

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]; } } } } indicatorIcons的{​​{1}}属性:

variant

我为PageIndicator网址使用了 property variant indicatorIcons: [ "qrc:/icons/qtlogo.png", "qrc:/icons/qtlogo1.png", "qrc:/icons/qtlogo2.png" ] 个对象数组,因为它似乎无法做到

string

QRC

delegate: detailsViewIndicator.indicatorImages[detailsView.currentIndex]

我遇到的问题是图像的实际加载,我感觉它与我上面描述的indicatorImages问题有关。使用代码

property list<Image> indicatorImages: [
  Image { source: "..." },
  Image { source: "..." },
  Image { source: "..." }
]

我第一次运行我的应用程序时得到:

enter image description here

这是因为最初选择的索引是list,因此会生成 delegate: Image { source: detailsViewIndicator.indicatorIcons[detailsView.currentIndex] // ... } 0,所有页面指示项都会填充。如果我选择其他两个中的一个作为最初选择的页面,我将分别获得Imagesource: "qrc:/icons/qtlogo.png"

qrc:/icons/qtlogo1.png中轻扫(点击qrc:/icons/qtlogo2.png)会导致

enter image description here

enter image description here

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

点击会让事情变得更有趣。在下面的屏幕截图中,我在初始化后点击了第二页指示项(SwipeView作为PageIndicator的来源):

enter image description here

接下来,我点击了第三页指标项目:

enter image description here

经过多次点击后我得到了:

enter image description here

显然,事情并非如此。我希望从开始到结束始终保持最终结果,无论哪个页面被刷掉或点击了页面指示项目。

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

1 个答案:

答案 0 :(得分:3)

  

由于某些原因,非活动状态根本不起作用

我假设这是一个拼写错误,因为使用interactive属性对我有用(Qt 5.7):

import QtQuick 2.7
import QtQuick.Controls 2.0

ApplicationWindow {
    visible: true

    PageIndicator {
        count: 3
        interactive: true
        onCurrentIndexChanged: print(currentIndex)
    }
}

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

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]

顺便说一句,指定图标源的一种更简单的方法是使用字符串连接(并为您的文件提供匹配的相应命名):

source: "qrc:/icons/qtlogo" + index + ".png"

在您添加的代码中,SwipeView未将currentIndex设置为currentIndex的{​​{1}}。你可以这样做:

PageIndicator

完整的例子:

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.bottomanchors.top)将无效。只能在垂直布局的直接子节点中使用水平锚点,反之亦然。