代码之家  ›  专栏  ›  技术社区  ›  K.Tsakalis

qt qml TypeError:无法调用未定义的方法“create\U PWM”

  •  0
  • K.Tsakalis  · 技术社区  · 8 年前

    我正在为信号生成设备开发一个应用程序的GUI,该设备将支持多个通道,呈现类似于控制台混音器的通道样式。在菜单栏中,用户应能够配置3种信号之间的通道使用。每种类型将在主窗口的不同选项卡中包含各自通道的总和。 “配置.qml” 包含信号处理程序和 “TabArea.qml” 包含javascript函数 创建\u PWM(countPWM) .

    简而言之,我的主窗口由以下组件组成 设备 , 菜单栏 , 工具 选项卡区域 . 在…内 菜单栏 我在名称下动态创建一个对话框组件 配置 . 中存在一个从中检索默认信息的表 表格模型 . 用户可以修改模型,单击“保存”按钮时,我希望根据模型数据在相应选项卡上描述通道。

    \\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文件都在同一目录中声明。因此 选项卡区域 组件在中可见 未接受 处理程序。此外 id:信道SPWM 声明为 tabAreaRoot 项,因此也可在组件外部调用。

    问题是,当我尝试在onActivated处理程序中调用create\u PWM时,我得到了以下结果:

    qrc:/Configuration.qml:181: TypeError: Cannot call method 'create_PWM' of undefined
    

    我知道这是因为 信道SPWM 在信号处理程序中不“可见”。但为什么呢?如上所述,即使在我键入 选项卡区域。信道SPWM。 QtCreator编辑器向我显示了可用的选项,这意味着此id由当前作用域接受。

    我还试图通过将 创建\u PWM 在一个单独的js文件中,当忽略activated()信号时,从那里调用它。在这种情况下,我没有得到TypeError 但是 未在所需位置创建所需通道。

    我还检查了id为 信道SPWM 在处理程序内调用之前未销毁。(我想还是检查一下好)

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

    提前谢谢你。

    1 回复  |  直到 8 年前
        1
  •  1
  •   K.Tsakalis    8 年前

    问题已解决。

    似乎我无法直接从动态创建的对象与任何其他qml文件交换数据 除了 它是父主qml文件。

    因此,我必须在 菜单栏。qml公司 并将其连接到 配置qml公司 如上所述 here . 这样,我通过 countPWM 父项的参数 配置按钮 然后我可以打电话给 create_PWM(countPWM) 从那里开始,使用 选项卡 在中实例化的对象 主窗口。qml公司 . 因此,新创建的PWM通道将是现有对象的子对象,并放置在正确的选项卡中。

    \\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);
    }
    
    推荐文章