简体   繁体   English

在 QML 中添加菜单时出错

[英]Error adding a Menu in QML

I have the following code:我有以下代码:

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

When I run it and click, the following message appears:当我运行它并单击时,出现以下消息:

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

Why is this?为什么是这样?

EDIT: Getting the advice from https://stackoverflow.com/users/24283/timday I did this:编辑:从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") }
    }
}

However, I cannot get the menu to show.但是,我无法显示菜单。

EDIT: Since it seems impossible to do what I want, I ended up with the recommendation of timday:编辑:由于似乎不可能做我想做的事,我最终得到了 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") }
    }
}

You need to actually have a Menu to your MenuBar to add MenuItem s to.您实际上需要在MenuBar中添加一个Menu才能将MenuItem s 添加到其中。 Like this:像这样:

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");
    }
  }
}

This (run with Qt5.5.0's qmlscene) starts with a "Tests" Menu in the bar, and adds a "Test" item to it every time you click (away from the menubar).这(使用 Qt5.5.0 的 qmlscene 运行)以栏中的“测试” Menu开始,每次单击(远离菜单栏)时都会向其中添加一个“测试”项。 You have to click to open the menu to see the items of course.您必须单击以打开菜单才能查看项目。

Dynamic creation of Menu s is a little harder;动态创建Menu有点难; see Qt.createQmlObject or Qt.createComponent docs.请参阅Qt.createQmlObjectQt.createComponent文档。 (It may be simpler to just declare all the ones you need in your code, but with their visible property wired to whatever logic is appropriate). (在代码中声明您需要的所有内容可能更简单,但将它们的visible属性连接到任何适当的逻辑)。

Update : as you note in your updated question, and I've just confirmed myself, simply adding a dynamically created Menu as a child of MenuBar seems to be insufficient to get the Menu to appear.更新:正如您在更新的问题中所指出的,我刚刚确认了自己,简单地添加一个动态创建的Menu作为MenuBar的子项似乎不足以让Menu出现。 I note it also doesn't result in the MenuBar 's menus list getting any bigger.我注意到它也不会导致MenuBarmenus列表变得更大。 Unfortunately it's not easy to append to QML lists , they're different from JavaScript arrays.不幸的是,附加到 QML列表并不容易,它们与 JavaScript 数组不同。 And there may be something funny about MenuBar... even attempting to assign a new list of menus, or an empty list, to it results in an error message. MenuBar 可能有一些有趣的地方……即使尝试为其分配新的菜单列表或空列表,也会导致错误消息。 Might be worth raising an issue/request for better (or easier, if it is possible somehow) dynamic MenuBar Menu item in the QtJira... but I suspect any restrictions may arise from Qt's use of native menus on some platforms, forcing least-common-denominator levels of functionality maybe. QtJira 中的动态MenuBar Menu项可能值得提出更好(或更简单,如果可能的话)的问题/请求......但我怀疑 Qt 在某些平台上使用本机菜单可能会产生任何限制,至少强制 -公分母级别的功能可能。

For a "Plan B" using initially hidden placeholders, this works sensibly on my Linux system:对于使用最初隐藏占位符的“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")
    }
  }
}

More general point: it occurs to me I'm slightly suspicious of any application design which is predicated on having a very dynamic set of menu bar menus to show the user.更一般的观点:我觉得我对任何以具有一组非常动态的菜单栏菜单来向用户显示为前提的应用程序设计都有些怀疑。 Sort of the whole point of the menu UX pattern is that it's pretty static and users' "muscle memory" lets them navigate it fast... but if menus are fairly randomly coming and going that'll break.菜单 UX 模式的全部要点是它非常静态,用户的“肌肉记忆”让他们可以快速导航……但是如果菜单相当随机地来来去去,那将会中断。 (OK some applications might present a different set of menus in a couple of different modes eg IDEs with edit/debug modes, but that'd be quite doable with the "Plan B" style above and QML's notion of states and wiring menu visibility to application state). (好吧,某些应用程序可能会在几种不同的模式下显示一组不同的菜单,例如具有编辑/调试模式的 IDE,但是使用上面的“Plan B”样式和 QML 的状态概念和布线菜单可见性,这将是完全可行的应用状态)。

I found a solution for "showing" problem.我找到了“显示”问题的解决方案。 Digging in MenuBarPrivate gave me an idea to use menusChanged() signal and it actually works.挖掘 MenuBarPrivate 给了我一个使用 menusChanged() 信号的想法,它确实有效。

Menu {
   id: foo
   ...
}

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM