首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >qml :无法调用未定义的方法“create_PWM”

qml :无法调用未定义的方法“create_PWM”
EN

Stack Overflow用户
提问于 2018-01-26 09:52:37
回答 1查看 2.4K关注 0票数 0

我正在开发一个用于信号生成设备的GUI应用程序,它将支持多个通道,类似于控制台混频器的信道样式。在菜单栏中,用户应该能够在三种类型的信号之间配置通道的使用。每种类型都将在主窗口的不同选项卡中包含各个通道的和。"Configuration.qml"包含信号处理程序,"TabArea.qml"包含javascript函数create_PWM(countPWM).。

简而言之,我的mainWindow由组件设备、MenuBar、工具和TabArea组成。在MenuBar内部,我在名称配置下动态创建一个对话框组件。存在一个从tableModel检索默认信息的表。用户可以修改模型,当单击Save按钮时,考虑到模型数据,我希望在相应的选项卡上描述通道。

代码语言:javascript
复制
\\MainWindow.qml
Item {
id: mainWindow
width: 1200
height: 800

Rectangle {
    id: background
    color: "#d7dfda"
    anchors.fill: parent

    MenuBar {
        id: menuBar
        anchors {
            left: parent.left
            top: parent.top
        }
        height: 40
    }
    Tools {
        id: toolBar
        y: menuBar.height
        height: implicitHeight
        anchors {
            left: parent.left
            right: parent.right
            top: menuBar.bottom
            bottom: devices.top
        }
        channelsPWM: tabs.channelsPWM
        channelsFrequency: tabs.channelsFrequency
    }

    Devices {
        id: devices
        anchors {
            //                top: menuBar.down
            top: toolBar.bottom
            left: parent.left
            right: tabs.left
        }
        height: 3 * parent.height / 8
        //            y: menuBar.height
        y: toolBar.height
    }

    TabArea {
        id: tabs
        //            y: menuBar.height
        y: toolBar.height
        x: parent.width / 8
        anchors {
            //                top: menuBar.bottom
            top: toolBar.bottom
        }
        width: 3 * parent.width / 4
        height: 3 * parent.height / 4
    }
}
}


\\MenuBar.qml
Item {
id: menuToolBar
Button {
    id: fileButton
    text: "File"
    anchors.left: parent.left
    anchors.top: parent.top
    height: 40
    onClicked: fileMenu.open()
    onHoveredChanged: hovered? fileButton.font.bold = true : fileButton.font.bold = false
    Menu {
        id: fileMenu
        y: parent.height
        MenuItem {
            text: "New Project      Ctrl+N"
            onTriggered: newDialog.open()

            }
        MenuItem {
            text: "Open Project     Ctrl+O"
            onTriggered: openDialog.open()
        }
    }
}

Button {
    id: editButton
    y: 0
    text: "Edit"
    anchors.left: fileButton.right
    anchors.leftMargin: 0
    anchors.top: parent.top
    height: fileButton.height
    onHoveredChanged: hovered? editButton.font.bold = true : editButton.font.bold = false
    onClicked: editMenu.open()
    Menu {
        id: editMenu
        y: parent.height
        MenuItem {
            text: "Undo             Ctrl+Z"
        }
        MenuItem {
            text: "Cut              Ctrl+X"
        }
        MenuItem {
            text: "Copy             Ctrl+C"
        }
        MenuItem {
            text: "Paste            Ctrl+V"
        }
    }
}

Button {
    id: configurationButton
    text: "Configuration"
    anchors.left: editButton.right
    anchors.top: parent.top
    height: editButton.height
    onHoveredChanged: hovered? configurationButton.font.bold = true : configurationButton.font.bold = false
    onClicked: {
        var component = Qt.createComponent("Configuration.qml");
        if( component.status !== Component.Ready )
        {
            if( component.status === Component.Error )
                console.debug("Error:"+ component.errorString() );
            return; // or maybe throw
        }
        var dialog =component.createObject(configurationButton);
        dialog.channelConfigDialog.open();
    }
}

Button {
    id: helpButton
    y: 0
    text: "Help"
    anchors.left: configurationButton.right
    anchors.leftMargin: 0
    anchors.top: parent.top
    height: fileButton.height
    onHoveredChanged: hovered? helpButton.font.bold = true : helpButton.font.bold = false
    onClicked: helpMenu.open()
    Menu {
        id: helpMenu
        y: parent.height
        MenuItem {
            text: "Contents"
        }
        MenuItem {
            text: "Index"
        }
        MenuItem {
            text: "Context Help             F1"
        }

    }
}

/**
  More Buttons for Menu implementation can be added here
  **/

FileDialog {
    id: openDialog
    title: "Please choose a Project."
    /**
      The backend behavior needs to be added here in order to determine
      what the application's actions will be for the selected files etc.
      e.g. onAccepted: {}
            onRejected: {}
      **/

}}
\\Configuration.qml
Item{
property alias channelConfigDialog: channelConfigDialog
Dialog {
    id: channelConfigDialog
    modality: Qt.WindowModal
    title: "Channel Configuration."
    height: 500
    width: 500
    standardButtons: Dialog.Save | Dialog.Cancel
    property int totalChannels: 30

    ListModel {
        id: tableModel
        Component.onCompleted: {
            for (var i=0;i<channelConfigDialog.totalChannels;i++){
                append({"name": "Channel"+(i+1), "use": "PWM", "data": "Raw", "conversion": ""});
            }
        }
    }

    Component {
        id: usageComboDel
        Item{
            anchors.fill: parent
            ComboBox {
                id: usageCombo
                model:
                    ListModel{
                        id: usageModel
                        ListElement {
                            text: "PWM"
                        }
                        ListElement {
                            text: "Frequency"
                        }
                        ListElement {
                            text: "BLDC"
                        }
                        }
                currentIndex: 0
                height: 16
                anchors.fill: parent
                onCurrentTextChanged: {
                    tableModel.setProperty(styleData.row,"use",currentText);

                }

    }


    Component{
        id: dataTypeComboDel
        Item{
            id: itemDataTypeComboDel
            anchors.fill: parent
            ComboBox {
                id: dataTypeCombo
                model: ["Raw", "Phys"]
                currentIndex: 0
                height: 16
                anchors.fill: parent
                onCurrentTextChanged: {
                    tableModel.setProperty(styleData.row,"data",currentText);
                    sample()
                }
                }
            function sample(){
                for (var i=0;i<tableConfig.rowCount;i++){
                    var temp = tableModel.get(i).name;
                    console.log(temp);
                    console.log(tableModel.get(i).use + ", " + tableModel.get(i).data);
                    }
            }
                }
    }
    Component{
        id: conversionRuleComboDel
        Item{
            id: itemConversionRuleComboDel
            anchors.fill: parent
            ComboBox {
                id: conversionRuleCombo
                model: ["","Linear", "Ranges", "Quadtratic", "Logarithmic", "Mathematical function"]
                currentIndex: -1
                height: 16
                anchors.fill: parent
                onCurrentTextChanged: {
                    tableModel.setProperty(styleData.row,"conversion",currentText);
                }
                }

        }

    }


    TableView {
        id: tableConfig
        model: tableModel
        anchors.fill: parent


        TableViewColumn{
            role: "name"
            title: "Channels"
            width: tableConfig.width/ tableConfig.columnCount

        }
        TableViewColumn{
            id: usageCol
            property alias delagata: usageComboDel
            title: "Usage"
            delegate: usageComboDel
            width: tableConfig.width/tableConfig.columnCount
        }
        TableViewColumn{
            title: "Data Type"
            delegate: dataTypeComboDel
            width: tableConfig.width/tableConfig.columnCount
        }
        TableViewColumn{
            id: conversionRuleClmn
            title: "Coversion Rule"
            delegate: conversionRuleComboDel
            width: tableConfig.width/tableConfig.columnCount
        }
    }

    onAccepted: {
        var countPWM = 0;
        var countFrequency = 0;
        for (var i=0; i<tableModel.count; i++){
            if ( tableModel.get(i).use === "PWM" ){
                countPWM++;
            }
            else if (tableModel.get(i).use === "Frequency"){
                countFrequency++;
            }
        }
        TabArea.channelsPWM.create_PWM(countPWM);

        }
}
}
\\TabArea.qml
Item{
id: tabAreaRoot
property alias channelsPWM: channelsPWM
property alias channelsFrequency: channelsFrequency

TabBar {
    id: tabBar
    TabButton {
        text: qsTr("PWM Output")
        width: implicitWidth
    }
    TabButton {
        text: qsTr("Frequency Output")
        width: implicitWidth
    }
    TabButton {
        text: qsTr("BLDC Emulation")
        width: implicitWidth
    }
}

StackLayout {
    id: tabLayout
    anchors.top: tabBar.bottom
    currentIndex: tabBar.currentIndex
    width: parent.width
    height: parent.height
    Rectangle {
        color: background.color
        border.width: 2
        ScrollView{
            id: scrollPWM
            anchors.fill: parent
            contentItem: channelsPWM.children
            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn
            RowLayout{
                id: channelsPWM
                spacing: 0
                Layout.fillHeight: true
                Layout.fillWidth: true


                function create_PWM(countPWM){
                    for (var i=0;i<countPWM;i++){
                        var component = Qt.createComponent("PWM.qml");
                        if( component.status !== Component.Ready )
                        {
                            if( component.status === Component.Error )
                                console.debug("Error:"+ component.errorString() );
                            return; // or maybe throw
                        }
                        var channels =component.createObject(channelsPWM, { "id": "channelPWM"+(i+1), "channelText.text": "Channel"+(i+1)});
                    }
                    }
            }
        }

    }/* Each tab will be a row layout containing column positioners for each channel */
    Rectangle {
        color: background.color
        border.width: 2
        ScrollView{
            id: scrollFrequency
            anchors.fill: parent
            contentItem: channelsFrequency.children
            horizontalScrollBarPolicy: Qt.ScrollBarAlwaysOn
            RowLayout{
                id: channelsFrequency
                spacing: 0
                Layout.fillHeight: true
                Layout.fillWidth: true
                function create_Frequency(countFrequency){
                    for (var i=0;i<countFrequency;i++){
                        var component = Qt.createComponent("Frequency.qml");
                        if( component.status !== Component.Ready )
                        {
                            if( component.status === Component.Error )
                                console.debug("Error:"+ component.errorString() );
                            return; // or maybe throw
                        }
                        var channels =component.createObject(channelsFrequency, { "id": "channelFrequency"+(i+1), "channelText.text": "Channel"+(i+1)});
                    }
                    }
                }
        }

    }
    Rectangle {
        color: background.color
        border.width: 2


    }
}

}

两个qml文件都在同一个目录中声明。因此,TabArea组件在onAccepted处理程序中是可见的。此外,id: channelsPWM被声明为tabAreaRoot项的属性,因此也可在组件之外调用。

问题是,当我试图在create_PWM处理程序中调用onActivated时,会得到以下信息:

代码语言:javascript
复制
qrc:/Configuration.qml:181: TypeError: Cannot call method 'create_PWM' of undefined

我理解这是因为channelsPWM在信号处理程序中是“不可见的”。但这是为什么?如前所述,即使在我输入TabArea.channelsPWM时也是如此。等等,QtCreator编辑器向我展示了可用的选项,这意味着这个id是由当前作用域获取的。

我还试图“绕过”这个问题,将create_PWM放在单独的js文件中,当已激活()信号被省略时,从那里调用它。在这种情况下,我没有得到TypeError ,但是所需的通道不是在所需的位置创建的。

我还检查了在处理程序中调用之前,没有销毁id channelsPWM的对象。(我想无论如何检查一下是好的)

事情可能会变得更加混乱,因为我希望根据用户的配置动态创建这些通道。因此,如果我得到这个wright,创建它们的函数需要与通道的RowLayout父函数放在同一个qml中。

提前谢谢你。

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2018-01-29 11:06:15

问题解决了。

看起来,我不能直接从动态创建的对象与任何其他qml文件交换数据,除了,它的主qml文件。

因此,我必须在MenuBar.qml中创建一个方法,并将其连接到Configuration.qml中的自定义信号,就像描述的这里一样。这样,我将countPWM参数传递给父项configurationButton,然后使用在MainWindow.qml中实例化的create_PWM(countPWM)对象从那里调用create_PWM(countPWM)。因此,新创建的PWM通道将是现有对象的子对象,并放置在正确的选项卡中。

代码语言:javascript
复制
\\MenuBar.qml
(rest of code)
function sendParams(counter){
        tabs.channelsPWM.create_PWM(counter);
    }


\\Configuration.qml
(rest of code)
signal saved(int counter)
onSaved: {
        console.log("I just sent the counter");
}
onAccepted: {
        var countPWM = 0;
        var countFrequency = 0;
        for (var i=0; i<tableModel.count; i++){
            if ( tableModel.get(i).use === "PWM" ){
                countPWM++;
            }
            else if (tableModel.get(i).use === "Frequency"){
                countFrequency++;
            }
        }
        saved.connect(parent.sendParams);
        saved(countPWM);
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/48458995

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档