为什么我的QML背景透明度会因宽度设置而中断?

时间:2017-11-28 18:56:24

标签: qt qml transparency

我遇到了一些奇怪的QML行为。基本上,我有一个TabBar标题,其中有几个标签。我希望background元素对于每个元素大致相同,但其中一些我希望能够动态地改变颜色。所以我有一个组件:

Component {
    id: standardBackground
    Rectangle {
        opacity: parent.parent.checked ? 0 : (parent.parent.pressed ? 0.8 : 1)
        color: tabColor
    }
}

对于每个TabButton,我正在做:

TabButton {
    text: qsTr("Tab 1")
    background: Loader { sourceComponent: standardBackground }
    height: 60
}

这很有效,但我遇到了一些非常奇怪的错误。首先,以这种方式运行它会给我以下QML警告:

QML TabButton: Binding loop detected for property "implicitWidth"

所以我想我可以通过向我的组件中的width: parent.width添加Rectangle来解决这个问题。这个确实使警告静音,但由于某种原因,它使第一个标签始终是透明的,无论它是否被点击。这仅影响第一个选项卡。我不知道为什么会这样。

但是,当我设置width: <anything>时,这就解决了这两个问题:没有警告和正确的透明度。玩宽度的不同设置不会导致明显的变化,只要它是正面的。所以我把它设置为1.如果我将它设置为0,我得到相同的&#34;隐式宽度&#34;警告。

所以有几个不同的问题:

  • 为什么在设置width: parent.width时组件的透明度会中断?

  • 为什么我可以将宽度设置为任何常量值而不会影响GUI呢?

  • 有没有更好的方法来消除有关隐式宽度的警告?

这是我的完整代码(简化为较少的标签):

import QtQuick 2.6
import QtQuick.Layouts 1.3
import QtQuick.Controls 2.0
import QtQuick.Controls.Material 2.0
import QtQuick.Controls.Universal 2.0
import Qt.labs.settings 1.0
import QtQuick.VirtualKeyboard 2.1
import QtQuick.VirtualKeyboard.Settings 2.1

import "DataEntry"

ApplicationWindow {
    id: window
    width: 1280
    height: 1024
    visible: true
    title: "Hello World"


    property var tabColor: "#353637"
    property var dummy: InputContext.focus

    Settings {
        id: settings
        property string style: "Universal"
    }

    Component {
        id: standardBackground
        Rectangle {
            opacity: parent.parent.checked ? 0 : (parent.parent.pressed ? 0.8 : 1)
            color: tabColor
            width: 1
        }
    }

    header: TabBar {
        id: bar
        width: parent.width
        height: 60

        TabButton {
            text: qsTr("Tab 1")
            background: Loader { sourceComponent: standardBackground }
            height: 60
        }

        TabButton {
            text: qsTr("Tab 2")
            background: Loader {
                sourceComponent: standardBackground

                function getTabColor(error){
                    if (error)
                        return '#cccc00'

                    return window.tabColor
                }

                property var tabColor: getTabColor(hasError)
            }
            height: 60
        }
    }

    StackLayout {
        id: viewStack
        width: parent.width
        anchors.fill: parent
        currentIndex: bar.currentIndex

        tab1 {
        }

        tab2 {
        }
    }
}

1 个答案:

答案 0 :(得分:0)

正如我们所做的那样,我倾向于只回答一个问题。对你而言,我选择了绑定循环的问题。

绑定循环的原因是documented here.

您没有为Loader指定大小,因此Loader的隐式宽度设置为加载的Item指定的宽度。在这里,您将大小设置为与Loader的大小相同。现在这不是问题,结果只是0

现在我们在Button中加入了implicitSize设置其样式项目。这里Loader实例化为宽度为0,然后调整大小以填充implicitWidth的{​​{1}},这是{没有大小的背景),具体取决于Buttontext s。

现在我们更新一轮。因此,padding的{​​{1}}取决于implicitWidth的{​​{1}},其Rectangle取决于width的宽度。此外,Loader的宽度取决于implicitWidth的宽度,具体取决于Rectangle,而后者取决于Loader ...

即使没有直接问题,也很容易检测到绑定循环,因为系统在第一次迭代中正在稳定。