簡體   English   中英

QML中父級屬性更改時更改子級屬性

[英]Change children property when parent property changes in QML

我有3個檔案。 main.qml,Guide.qml和ChannelViewer.qml我的主類包含2個組件和一個加載器,這里是代碼

main.qml

import QtQuick 2.0

Rectangle {
    id:loader
    color: "black"
    property string channelName
    property string channelURL

    Component{
        id:tv
        ChannelViewer{}
    }

    Component{
        id:guide
        Guide{}
    }

    Loader
    {
        id: pageLoader
        anchors.fill:parent
        focus:true
        sourceComponent: tv
    }

    Connections{
        target:pageLoader.item
        onChangeChannel:{
            channelName=name
            channelURL=url
        }
    }

    Keys.onPressed: {
        event.accepted = true;
        if (event.key === Qt.Key_I) {
            pageLoader.sourceComponent = tv;
        }
        else if(event.key === Qt.Key_G) {
            pageLoader.sourceComponent = guide;
        }
    }
}

現在,如果我按“ G”,我將被無任何問題地移動到指南文件中。在我的指南頁面中,我能夠向main.qml發送信號並更新main中的name屬性。

Guide.qml

Item {
    signal changeChannel(string url, string name)
    Loader {
        id: pageLoader
        anchors.fill:parent
        sourceComponent: guide
        focus:true
    }

    Keys.onPressed: {
        if(event.key === Qt.Key_Escape) {
            pageLoader.source = "main.qml";
        }
        event.accepted = true;
    }

    Component {
        id:guide

        Rectangle {
            color:"lightblue"

            Keys.onPressed: {
                if(event.key === Qt.Key_Return) {
                    changeChannel(menuContent.currentItem.ch_url, menuContent.currentItem.ch_name)
                    pageLoader.source = "main.qml";
                }
                event.accepted = true;
            }
        }
    }
}

但是現在當我在Guide.qml中按“ Return”時,我將被帶回到main.qml(Channelname和ChannelURL將被成功更新),而我的main.qml現在將帶我到ChannelViewer.qml,這就是問題所在我的ChannelViewer.qml將不會收到更新的channelName和channelURL。 而且我不確定我在做什么錯。

ChannelViewer.qml

import QtQuick 2.0
import VLCQt 1.0

Rectangle {
    id:root
    width: 640
    height: 480
    color: "black"
    focus:true

    Loader
    {
        id: pageLoader
        anchors.fill:parent
    }

    MouseArea {
        anchors.fill: parent
        onClicked: {
            console.log(channelURL)
        }
    }

    Keys.onPressed: {
        if (event.key === Qt.Key_I) {
            event.accepted = true;
            if(channelInfo.visible === true) {
                channelInfo.visible=false;
            }
            else {
                channelInfo.visible=true;
            }
        }
    }

    VlcVideoPlayer {
        id: vidwidget
        anchors.fill: parent
        url:channelURL

        ChannelInfo{
            id:channelInfo
            anchors.bottom: parent.bottom
            anchors.bottomMargin: ((parent.height*5)/100)
            anchors.horizontalCenter: parent.horizontalCenter
            width:parent.width - ((parent.width*10)/100)
            height: (parent.height*20)/100
            backgroundOpacity: 0.7
            radius:10
            channelNameProp: channelName
            channelNumberProp: "1"
            headerIcon: "imgs/television_32x32.png"
        }
    }
}

編輯:我的ChannelInfo.qml的代碼

import QtQuick 2.0

Item {
    id:channelinfo
    property color backgroundColor: "blue"
    property color headerBackgroundColor: "lightblue"
    property color headerNameColor: "black"
    property color borderColor: "black"
    property color channelNameColor: "white"
    property color channelNumberColor: "white"
    property real borderWidth:0
    property real radius:0
    property real backgroundOpacity: 0.5
    property string menuTitle : "TV Channels"
    property string channelNameProp
    property string channelNumberProp
    property url headerIcon: "imgs/television.png"

    visible:false

    Rectangle{
        id:root
        width:channelinfo.width
        height:channelinfo.height
        color:channelinfo.backgroundColor
        border.color:channelinfo.borderColor
        border.width: channelinfo.borderWidth
        radius:channelinfo.radius
        opacity:channelinfo.backgroundOpacity
        visible: parent.visible

        Rectangle{
            id:header
            anchors.top:parent.top
            //            width:(parent.width*40)/100
            width: parent.width
            height: (parent.height*30)/100
            radius: channelinfo.radius
            color:channelinfo.headerBackgroundColor
            Image{
                source:channelinfo.headerIcon
                anchors.left: parent.left
                anchors.leftMargin: 10
                anchors.verticalCenter: parent.verticalCenter
                anchors.verticalCenterOffset: -4
            }

            Text{
                id:headerTitle
                anchors.left: parent.left
                anchors.leftMargin: 50
                anchors.verticalCenter: parent.verticalCenter
                width:parent.width
                wrapMode: Text.WordWrap
                color:channelinfo.headerNameColor
                text:menuTitle
                font.pixelSize: Math.round(parent.height/2)
                font.bold: true
            }
        }

        Rectangle{
            id:content
            anchors.bottom: parent.bottom
            width:parent.width
            height:parent.height-header.height
            color:"transparent"
            Text{
                id:channelName
                anchors.left: parent.left
                anchors.leftMargin: 50
                anchors.verticalCenter: parent.verticalCenter
                color:channelinfo.channelNameColor
                text:channelNameProp
                font.pixelSize: Math.round(parent.height/4)
                font.bold: true
            }
            Text{
                id:channelNumber
                anchors.right: parent.right
                anchors.rightMargin: 20
                anchors.verticalCenter: parent.verticalCenter
                color:channelinfo.channelNumberColor
                text:channelNumberProp
                font.pixelSize: Math.round(parent.height/4)
                font.bold: true
            }
        }
    }
}

VLCPlayer的Github頁面https://github.com/vlc-qt/

如果您將要具有這樣的固定結構,為什么還要打擾信號,您也可以簡單地:

 Keys.onPressed: {
                if(event.key === Qt.Key_Return) {
                    channelName = menuContent.currentItem.ch_name
                    channelURL = menuContent.currentItem.ch_url
                    pageLoader.source = "main.qml";
                }
                event.accepted = true;
            }

然后刪除不必要的部分:

Connections{
    target:pageLoader.item
    onChangeChannel:{
        channelName=name
        channelURL=url
    }
}

由於channelNamechannelURL是在channelURL文件的根對象中聲明的,因此由於動態作用域,應該可以從嵌套在樹上的對象中訪問它們。

因此,發布相關代碼后,您將擁有:

        Text{
            id:channelName

在您的ChannelInfo對象中,該對象遮蓋了main.qml聲明的channelName屬性。 養成一致的命名約定的習慣是一個好主意。 例如,由於這是一個ID,因此我個人會使用id: _cName ,這樣可以最大程度地減少發生此類沖突的幾率。

更新:

我能想到為什么它不起作用的唯一另一個原因是,您正在通過執行諸如channelNameProp = something類的方法來破壞channelNameProp: channelName綁定。

這是一個簡單的示例,說明即使在涉及動態更改Loader項的情況下,動態范圍也適用 (只要您不遮擋任何東西):

// main.qml
ApplicationWindow {
  id: _cName
  visible: true
  width: 640
  height: 480
  property int value: 0
  Loader {
    id: loader
    source: "Obj.qml"
  }
}

// Rect.qml
Rectangle {
  id: rectangle
  width: 50; height: 100
  color: "red"
  Text {
    anchors.centerIn: parent
    text: value
  }
  MouseArea {
    anchors.fill: parent
    onClicked: {
      loader.source = "Obj.qml"
    }
  }
}

// Obj.qml
Rectangle {
  id: rectangle
  width: 50; height: 100
  color: "blue"
  MouseArea {
    anchors.fill: parent
    onClicked: {
      value++
      loader.source = "Rect.qml"
    }
  }
}

作為屬性

property string channelName
property string channelURL

具有更改信號並因此支持屬性綁定,我認為最簡單的方法是將第9-17行更改為

Component{
    id:tv
    ChannelViewer {
        id: channelViewer
        channelName: loader.channelName
        channelURL: loader.channelURL
    }
}

Component{
    id:guide
    Guide {
        id: guide
        channelName: loader.channelName
        channelURL: loader.channelURL
    }
}

如果Guide更改了channelName,則需要確保在loader對其進行更改。 您可以使用Binding -objects使綁定在分配( = )中保留。

所以這個工作,你需要創建的屬性channelNamechannelURL在你的根節點Guide.qml ABD你ChannelViewer.qml 然后,在這些文件里每一個地方,你可以使用完全合格的標識符: id.propertyName ,這將是如channelinfo.channelNameChannelInfo.qmlroot.channelNameChannelViewer.qml和一個id,你將需要設置(如再次root)在Guid.qml > root.channelName

  • 對綁定使用完全合格的標識符(該標識符始終包括idOfTheObject.propertyName有助於避免出現問題。 在某些情況下(定位,定位,調整大小), parent還可以,但是您可能不知道父級到底是什么。
  • 如果您確切知道代碼的使用方式和位置(例如,它本質上是較大對象的部分定義,並且永遠不會在其他上下文中使用),則動態范圍是一種幸運。 但是在這里您需要知道,如果父文件更改了內部api,則需要相應地修改子文件。 如果您認為該文件可能要重用,請避免動態作用域,而僅引用文件中定義的內容。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM