Ошибка добавления меню в QML

У меня есть следующий код:

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

Почему это?

РЕДАКТИРОВАТЬ: получить совет от 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") }
    }
}

Тем не менее, я не могу получить меню, чтобы показать.

РЕДАКТИРОВАТЬ: Поскольку кажется невозможным делать то, что я хочу, я закончил с рекомендацией Тимдей:

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

1 ответ

Вы должны на самом деле иметь Menu на ваш MenuBar добавить 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");
    }
  }
}

Это (запуск с qmlscene Qt5.5.0) начинается с "Тестов" Menu в панели, и добавляет элемент "Тест" к нему каждый раз, когда вы нажимаете (вдали от строки меню). Вы должны нажать, чтобы открыть меню, чтобы увидеть элементы, конечно.

Динамическое создание Menuс немного сложнее; увидеть Qt.createQmlObject или же Qt.createComponent Docs. (Может быть проще просто объявить все, что вам нужно в вашем коде, но с их visible свойство привязано к какой-либо логике).

Обновление: как вы отметили в своем обновленном вопросе, и я только что подтвердил, просто добавив динамически созданный Menu как ребенок MenuBar кажется недостаточным, чтобы получить Menu появляться. Я отмечаю, что это также не приводит к MenuBar"s menus список становится больше. К сожалению, нелегко добавить в списки QML, они отличаются от массивов JavaScript. И в MenuBar может быть что-то смешное... даже попытка назначить ему новый список меню или пустой список приводит к сообщению об ошибке. Возможно, стоит поднять вопрос / запрос на лучшую (или более легкую, если возможно, каким-либо образом) динамическую MenuBarMenu элемент в QtJira... но я подозреваю, что любые ограничения могут возникнуть из-за использования Qt нативных меню на некоторых платформах, возможно, для навязывания уровней функциональности с наименьшим общим знаменателем.

Для "Плана 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 с режимами редактирования / отладки, но это вполне выполнимо с использованием приведенного выше стиля "План Б" и представления состояний QML и видимости меню проводки для состояние приложения).

Нашел решение проблемы "показа". Копание в MenuBarPrivate натолкнуло меня на идею использовать сигнал menusChanged(), и он действительно работает.

Menu {
   id: foo
   ...
}

MenuBar {
   Component.onCompleted: {
        menus.push(foo)
        menusChanged()
    }
}
Другие вопросы по тегам