2017-08-03 253 views
0

我有3個文件。 main.qml,Guide.qml和ChannelViewer.qml 我的主類包含2個分量,在這裏裝載機是代碼在QML中更改父項屬性時的子項屬性

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「返回」我會被帶回main.qml(頻道名稱和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 
      } 
     } 
    } 
} 

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

回答

1

如果你想有這樣一個固定的結構,所以即使有信號打擾,你可以簡單地說:

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是在qml文件的根對象中聲明的,所以它們應該可以從樹中進一步嵌套的對象中訪問動態範圍的使用。

所以您發佈的相關代碼後,你有一個:

 Text{ 
      id:channelName 

ChannelInfo對象,它遮蔽了channelName財產,在main.qml聲明。養成一致命名約定的習慣是一個好主意。例如,由於這是一個ID,我個人會使用id: _cName,這樣可以最大限度地減少碰到這種衝突的機率。

更新:

唯一的其他原因,我能想到的,爲什麼它不工作是你的地方打破了channelNameProp: channelName通過執行類似channelNameProp = something結合。

下面是一個簡單的例子來說明動態作用域只是工作(只要你不影東西),甚至在涉及動態變化的裝載機項目情況:

// 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" 
    } 
    } 
} 
+0

我更喜歡這個信號,因爲您應該努力避免依賴動態範圍。雙向綁定可能會更好,但信號是恕我直言的良好開端。 – derM

+0

「你應該努力避免依賴動態範圍」 - 爲什麼? – dtech

+0

綁定之前我試過這個,它沒有工作。我又試了一次,仍然一樣。 main.qml從Guide.qml獲取更新的值,但是,ChannelViewer不會獲取更新的值。 –

0

由於性能

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 
    } 
} 

如果指南更改頻道名稱,你需要確保你改變它在loader。您可以使用Binding-對象使綁定生存分配(=)。

因此,這需要在Guide.qmlChannelViewer.qml的根節點中創建屬性channelNamechannelURL。然後,在這些文件裏每一個地方,你可以使用完全合格的標識符:id.propertyName,這將是在ChannelInfo.qmlroot.channelNameChannelViewer.qml e.g channelinfo.channelName和ID,你將需要設置(例如再次根)在Guid.qml - >root.channelName

  • 完全合格的標識符綁定,它總是包含idOfTheObject.propertyName的使用有助於避免出現問題。在某些情況下(定位,錨定,選擇大小)parent是可以的,但您可能不知道父母究竟是什麼)
  • 如果您確切知道如何以及如何使用代碼,動態範圍確實是一件幸事。如果它本質上是一個更大對象的部分定義,並且永遠不會在另一個上下文中使用。但是在這裏你需要知道,如果父文件改變了內部API,你需要相應地修改子文件。如果您認爲該文件可能需要重用,請避免動態範圍限制,並僅引用文件中定義的內容。
+0

不幸的是,我有之前嘗試過這種方法,並沒有工作。它說channelName是一個不存在的屬性。可能我做錯了什麼? –

+0

哦,你是對的。你的'ChannelViewer.qml'中沒有'channelName',也沒有你的'Guide.qml'。您只能設置文件根節點的屬性。 – derM

+0

你有鏈接到代碼或更好的文檔:'ChannelInfo','VlcVideoPlayer'?儘量避免綁定到未在與設置綁定相同的文件中聲明的屬性。在文件根節點中創建屬性,將內部屬性綁定到該節點。然後,您可以在使用組件時正確設置它們。 – derM