QML StackView 没有啥可推送的

Posted

技术标签:

【中文标题】QML StackView 没有啥可推送的【英文标题】:QML StackView replace nothing to pushQML StackView 没有什么可推送的 【发布时间】:2017-02-10 02:19:18 【问题描述】:

如何根据以下示例在页面之间正确切换:

import QtQuick 2.6
import QtQuick.Layouts 1.0
import Qt.labs.controls 1.0

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

StackView 
    id: stack
    anchors.fill: parent
    initialItem: hal1


Pane 
    id: hal1
    anchors.fill: parent
    background: Rectangle 
        id: mystart
        anchors.centerIn: parent
        color: "#2196F3"
    


Pane 
    id: hal2
    anchors.fill: parent
    Label 
        text: qsTr("Second page")
        anchors.centerIn: parent
    


footer: TabBar 
    id: tabBar
    currentIndex: 0
    TabButton 
        text: qsTr("First")
        onClicked: 
           if(stack.currentItem==hal1)
                console.log("dont switch hal1 !")
                return
          
          stack.replace(hal1)
        
    
    TabButton 
        text: qsTr("Second")
        onClicked: 
            if(stack.currentItem==hal2)
                console.log("dont switch hal2 !!")
                return
            
            stack.replace(hal2)
        
    
  

每当单击第一个选项卡时,我想获得矩形,而第二个选项卡我想获得我的简单标签。 我正在使用 qt labs controls 5.6 谢谢

编辑: 看起来此代码仅适用于调试构建而不适用于发布构建。在 msvc2015 窗口上测试。我不知道为什么会发生这种情况,任何指针?

好的,我附加了另一个示例项目here 以使这个案例更清楚。这里有两个问题,第一件事是我收到警告消息“StackView replace nothing to push”以及调试和发布版本之间的不一致行为。调试构建工作正常,我在发布构建时得到了意外的结果。

【问题讨论】:

应用程序启动时hal1 已经在堆栈上。当您按First 时,您正试图用hal1 替换hal1,这是没有意义的。 @folibis,感谢您指出这一点。我已经解决了这个问题,并且行为仍然相同。我在这里看到了非常奇怪的不一致行为。无论如何我已经在这里提交了关于这个案例的错误报告bugreports.qt.io/browse/QTBUG-58765 对我来说,我认为使用替换 StackView 并没有多大意义,因为堆叠容器的正确逻辑是推送。可能你需要SwipeView 或类似的东西。 我已经使用替换功能编写了许多 qml 东西,根据一些文档,这里的替换意味着简单的弹出“快捷方式”然后推送项目。我真的很喜欢这个:)。我想通过加载必要的页面来最小化内存消耗,而 StackView 是我真正的致命工具箱:) 正如@folibis 指出的那样,StackView 的使用似乎很奇怪,因为它看起来不像你堆叠任何东西。提到的SwipeView 还试图通过只加载最多三页来保持低内存消耗,以实现平滑过渡。你的 StackView 不是这样 - 对象是在开始时创建的,永远保持活动状态,只有父母身份由 StackView 控制 【参考方案1】:

虽然我不清楚您的问题,但由于 cmets 太有限,无法解决您的代码的许多问题,因此我尝试回答。

首先进行编辑:

编辑:看起来此代码仅适用于调试构建而不适用于发布构建。在 msvc2015 窗口上测试。我不知道为什么会发生这种情况,任何指针?

因此,您的两个构建设置之间需要存在一些实质性差异。 检查差异,尤其是在构建目录中。任何挥之不去的文件,可能不应该来自旧版本? 一切都正确编译了吗?

然后到你的分层:

您的第一层是 StackView 在上面你有 hal1 你上面有 hal2

那么你就有了initialItem 集合,它将hal1 重生为StackView hal2 保持在顶部,直到您将其显示在 StackView 中,因此您应该首先看到 hal2

然后是您对内存消耗的误解:StackView 不会最小化内存消耗。 当您在StackView 上推送某些内容时,它只会重新设置为它的父级,并设置为可见。将其弹出时,它会重新设置为原始父级,并变为不可见。要验证我的声明,请记录 Component.onCompletedComponent.onDestruction。第一次发生在启动时,后者发生在应用程序关闭时,而不是在页面被推送弹出时。因此内存消耗一直。防止这种情况的唯一方法是动态创建它们。编辑正如 BaCaRoZzo 指出的那样,在使用 StackView 时保持低内存是重要的。可以做到,例如通过传递Component 而不是静态创建的Item。在这种情况下,StackView 负责创建,一旦从堆栈中弹出,对象就会被销毁。

folibis 提到的SwipeView 让事情变得更容易一些。由于它的default property 是Component 类型,所以您编写的SwipeView ... here ... 的所有内容都不会立即实例化,而是存储为组件,仅在需要时才实例化。这是在显示时,或可能很快显示(currentItem 的左侧或右侧)。所以我们可以看到,从内存消耗的角度来看,...Views 都可以有效地使用。不过,用法有不同的风格,SwipeViewStackView 的语义不同。通常SwipeView 看起来更自然,当有多个页面时并行StackView 是要走的路,当你完全按照它的名字所暗示的那样做时:stack Items

当谈到要走的路时:你为什么选择Qt.labs.controls而不是QtQuick.Controls 2.0?与labs-version 相比,它们往往更稳定,并且行为应该不太可能因其他版本而改变。

现在,我希望我对您有所帮助,即使我可能无法解决您的问题,因为您尚未在问题中说明。

【讨论】:

因为我们现在只讨论 2 个对象,是的:内存消耗是相同的,因为SwipeView 在内存中最多可以容纳三个对象。但是SwipeViewdefault property 似乎是default property Component,即使您还没有这样做,它也将所有内容都包装在Component 中。这意味着:SwipeView ... Component Item ... 的结果与SwipeView ... Item ... 相同。在这两种情况下,Item 仅在需要时创建(显示,或显示的旁边) 我已经更新了我的问题以使其更清晰。这对你来说更有意义吗?

以上是关于QML StackView 没有啥可推送的的主要内容,如果未能解决你的问题,请参考以下文章

如何以递归方式推送到StackView QML?

QML StackView:动态更改replaceEnter/Exit动画

如何使用QML StackView的status属性?

QML:在 StackView 中,水平可滑动的视觉效果会持续存在

stackland怎么把堆叠的卡牌拆开

如何在QML应用中得到一个Item的所有属性,信号及方法,qmlitem