在QML

时间:2017-08-03 05:45:02

标签: c++ qt qml qt5 qt-creator

我有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/

2 个答案:

答案 0 :(得分: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约束。

这是一个简单的示例,用于说明动态范围正常工作(只要您不影响任何内容),即使在涉及动态更改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"
    }
  }
}

答案 1 :(得分: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
    }
}

如果指南更改了channelName,您需要确保在loader中更改它。您可以使用Binding - 对象使绑定在赋值(=)之间生效。

因此,您需要在channelNamechannelURL的根节点中创建属性Guide.qmlChannelViewer.qml。然后,在这些文件中的每个位置,您使用完全限定的标识符:id.propertyName,例如channelinfo.channelName中的ChannelInfo.qmlroot.channelName中的ChannelViewer.qml并且您需要在Guid.qml - >中设置ID(例如,再次root) root.channelName

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