在 QML 中更改父属性时更改子属性

  • 本文关键字:属性 QML c++ qt qml qt5 qt-creator
  • 更新时间 :
  • 英文 :


我有3个文件。 main.qml, Guide.qml 和 ChannelViewer.qml 我的主类包含 2 个组件和一个加载器,这里是代码

主.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属性。

指南.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(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
}
}
}
}

Github页面用于VLCPlayer 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是在 qml 文件的根对象中声明的,因此由于动态作用域,它们应该可以从嵌套在树上更远的对象中访问。

因此,在您发布相关代码后,您有一个:

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

如果指南更改了频道名称,则需要确保在loader中更改它。您可以使用Binding-对象使绑定在赋值 (=( 中幸存下来。

所以这行得通,您需要在Guide.qmlabdChannelViewer.qml的根节点中创建属性channelNamechannelURL。然后,在这些文件中的每个位置,您使用完全限定的标识符:id.propertyName,例如channelinfo.channelNameChannelInfo.qml中,root.channelNameChannelViewer.qml中,以及您需要在Guid.qml中设置的id(例如再次root(->root.channelName

  • 对绑定使用完全限定的标识符(始终包含idOfTheObject.propertyName(有助于避免出现问题。在某些情况下(定位、锚定、调整大小(parent是可以的,但您可能不知道父级到底是什么(
  • 如果您确切地知道代码的使用方式和位置,例如,如果它本质上是较大对象的部分定义,并且永远不会在另一个上下文中使用,那么动态作用域是一种祝福。但是在这里你需要知道,如果父文件更改了内部 api,你需要相应地调整子文件。如果您认为该文件可能用于重用,请避免动态作用域,而仅引用文件中定义的内容。

相关内容

  • 没有找到相关文章

最新更新