在QML中添加菜单时出错

时间:2015-08-21 14:13:25

标签: qt qml qtquick2

我有以下代码:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4

ApplicationWindow {
    title: qsTr("Hello World!")
    width: 640
    height: 480
    visible: true

    menuBar: MenuBar {
        id: menuBar
    }

    MouseArea
    {
        anchors.fill: parent
        onClicked: { menuBar.menus.addItem("test") }
    }
}

当我运行它并单击时,会出现以下消息:

qrc:/main.qml:19: TypeError: Property 'addItem' of object [object Object] is not a function

为什么会这样?

编辑:从https://stackoverflow.com/users/24283/timday获取建议 我这样做了:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4

ApplicationWindow {
    title: qsTr("Hello World!")
    width: 640
    height: 480
    visible: true

    menuBar: MenuBar
    {
        id: menuBar

        function addMenu(text)
        {
            var newObject = Qt.createQmlObject('import QtQuick.Controls 1.4; Menu { id: test; title: "Test" }',
                menuBar, "dynamicSnippet1");

            newObject.visible = true
        }
    }

    MouseArea
    {
        anchors.fill: parent
        onClicked: { menuBar.addMenu("Test") }
    }
}

但是,我无法显示菜单。

编辑:由于似乎不可能做我想做的事情,我最终得到了timday的建议:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4

ApplicationWindow {
    title: qsTr("Hello World!")
    width: 640
    height: 480
    visible: true

    menuBar: MenuBar
    {
        id: menuBar

        Menu { id: menu00; visible: false; }
        Menu { id: menu01; visible: false; }
        Menu { id: menu02; visible: false; }
        Menu { id: menu03; visible: false; }
        Menu { id: menu04; visible: false; }
        Menu { id: menu05; visible: false; }
        Menu { id: menu06; visible: false; }
        Menu { id: menu07; visible: false; }
        Menu { id: menu08; visible: false; }
        Menu { id: menu09; visible: false; }
        Menu { id: menu10; visible: false; }
        Menu { id: menu11; visible: false; }
        Menu { id: menu12; visible: false; }
        Menu { id: menu13; visible: false; }
        Menu { id: menu14; visible: false; }
        Menu { id: menu15; visible: false; }
        Menu { id: menu16; visible: false; }
        Menu { id: menu17; visible: false; }
        Menu { id: menu18; visible: false; }
        Menu { id: menu19; visible: false; }

        property variant topMenus: [ menu00, menu01, menu02, menu03, menu04,
                                     menu05, menu06, menu07, menu08, menu09,
                                     menu10, menu11, menu12, menu13, menu14,
                                     menu15, menu16, menu17, menu18, menu19 ]
        property int currMenu: 0

        function addMenu(text)
        {
            if (currMenu == topMenus.length)
                console.log("Index out of range")
            else
            {
                var menu = topMenus[currMenu]
                menu.visible = true
                menu.title = text
                currMenu++
                return menu
            }
        }
    }

    MouseArea
    {
        anchors.fill: parent
        onClicked: { menuBar.addMenu("Test") }
    }
}

2 个答案:

答案 0 :(得分:2)

您需要MenuMenuBar添加MenuItem才能添加import QtQuick 2.4 import QtQuick.Window 2.2 import QtQuick.Dialogs 1.2 import QtQuick.Controls 1.4 ApplicationWindow { title: qsTr("Hello World!") width: 640 height: 480 visible: true menuBar: MenuBar { id: menuBar Menu { id: tests title: "Tests" } } MouseArea { anchors.fill: parent onClicked: { tests.addItem("Test"); } } } 。像这样:

Menu

这个(使用Qt5.5.0的qmlscene运行)以条形图中的“测试”Menu开始,并在每次单击(远离菜单栏)时向其添加“测试”项。您必须单击才能打开菜单以查看项目。

Qt.createQmlObject的动态创建有点困难;请参阅Qt.createComponentvisible文档。 (在代码中声明所需的所有内容可能更简单,但将Menu属性连接到适当的逻辑上。)

更新:正如您在更新的问题中所述,我刚刚确认了自己,只需添加一个动态创建的MenuBar作为Menu的孩子似乎是不足以让MenuBar出现。我注意到它也不会导致menus的{​​{1}}列表变得更大。不幸的是,附加到QML lists并不容易,它们与JavaScript数组不同。 MenuBar可能有些有趣......即使尝试为其分配新的菜单列表或空列表也会导致错误消息。可能值得提出一个问题/请求更好(或更容易,如果有可能的话)QtJira中的动态MenuBar Menu项......但我怀疑Qt使用本机可能会产生任何限制某些平台上的菜单,可能会强制实现最小公分母级别的功能。

对于使用最初隐藏占位符的“Plan B”,这在我的Linux系统上运行良好:

import QtQuick 2.4
import QtQuick.Window 2.2
import QtQuick.Dialogs 1.2
import QtQuick.Controls 1.4

ApplicationWindow {
  title: qsTr("Hello World!")
  width: 640
  height: 480
  visible: true

  menuBar: MenuBar {
    id: menubar
    Menu {title: "File"}
    Menu {id: testsmenu;title: "Tests";visible: false}
    Menu {title: "Help"}
  }

  MouseArea {
    anchors.fill: parent
    onClicked: { 
      testsmenu.visible=true
      testsmenu.addItem("Test")
    }
  }
}

更一般的观点:它发生在我身上我对任何应用程序设计都有点怀疑,这个应用程序设计的前提是有一组非常动态的菜单栏菜单来向用户显示。菜单UX模式的整个点是它非常静态,用户的“肌肉记忆”让它们快速导航......但是如果菜单是随机进出那么会破坏。 (好的一些应用程序可能会在几种不同的模式下呈现不同的菜单集,例如具有编辑/调试模式的IDE,但是对于上面的“Plan B”风格和QML的状态概念和布线菜单可见性来说,这是非常可行的。申请状态。)

答案 1 :(得分:0)

我找到了解决“显示”问题的方法。在MenuBarPrivate中进行挖掘使我有了使用menusChanged()信号的想法,并且它确实有效。

Menu {
   id: foo
   ...
}

MenuBar {
   Component.onCompleted: {
        menus.push(foo)
        menusChanged()
    }
}