Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. "Dynamically" add QML menu items based on C++?
Forum Update on Monday, May 27th 2025

"Dynamically" add QML menu items based on C++?

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
12 Posts 4 Posters 2.0k Views
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • Tom assoT Offline
    Tom assoT Offline
    Tom asso
    wrote on last edited by Tom asso
    #1

    I’d like my QML to display a group of menu items, where the number of items and the name of each item is specified in accompanying C++ code. Currently my QML displays a statically-defined set of items, like this:

    Menu {
      title: "Color table"
      Action {checkable: true; checked: true; text: qsTr("Haxby");                      
      Action {checkable: true; text: qsTr("BrightRainbow");                
      Action {checkable: true; text: qsTr("MutedRainbow");                
      Action {checkable: true; text: qsTr("Grayscale");
    

    Is it possible for the QML to retrieve the item names and number from the C++?
    And can the QML “dynamically” add each item to the menu when it doesn’t a priori know how many items there are? From my reading it seems it would look something like this, assuming my C++ object has been registered as a singleton:

    Menu {
    title: "TEST"
    Component.onCompleted: {
      for (var i = 0; i < myObject.nItems; i++)  {
        howToInsertItem named myObject.name[i] into menu???                   
      }
    }
    

    Thanks!

    1 Reply Last reply
    0
    • jeremy_kJ Online
      jeremy_kJ Online
      jeremy_k
      wrote on last edited by
      #2

      The documentation has a section on dynamic content, using Menu.addAction() or one of a set of similar functions.

      https://doc.qt.io/qt-6/qml-qtquick-controls-menu.html#dynamically-generating-menu-items

      Asking a question about code? http://eel.is/iso-c++/testcase/

      Tom assoT 1 Reply Last reply
      4
      • jeremy_kJ jeremy_k

        The documentation has a section on dynamic content, using Menu.addAction() or one of a set of similar functions.

        https://doc.qt.io/qt-6/qml-qtquick-controls-menu.html#dynamically-generating-menu-items

        Tom assoT Offline
        Tom assoT Offline
        Tom asso
        wrote on last edited by
        #3

        @jeremy_k - Awesome, thank you!

        Tom assoT 1 Reply Last reply
        0
        • Tom assoT Tom asso

          @jeremy_k - Awesome, thank you!

          Tom assoT Offline
          Tom assoT Offline
          Tom asso
          wrote on last edited by Tom asso
          #4

          @jeremy_k Thanks- looking at the link you provided, but I cannot find any examples of how Menu.addAction() (and other methods) are actually used in QML code. Do you know of an example? In my case, menu item names are stored in string array cmaps, and my QML looks like:

          Menu {
             title: "TEST"
             id: testMenu
             Component.onCompleted: {
             // Insert menu items with names 
             // from cmaps array	
             for (var i = 0; i < cmaps.length; i++)  { 
                console.log("map: ", cmaps[i])
                 testMenu.addItem({"text":cmaps[i]});
             } 
          }
          

          I can see the loop being executed, but items do not appear in the menu - do you know what I am missing? Thanks!

          jeremy_kJ 1 Reply Last reply
          0
          • Tom assoT Offline
            Tom assoT Offline
            Tom asso
            wrote on last edited by Tom asso
            #5

            I solved this with the following implementation, using Qt.createQmlObject() to create an Action and add it to the menu with Menu.addAction():

            Menu {
              title: "TEST"
              id: testMenu
              // Create and add Actions to menu
              Component.onCompleted: {
                // Insert menu items here, with number of items 
                // and item names as specified in the cmaps[] array that was
                // retrieved from C++
                for (var i = 0; i < cmaps.length; i++)  {
                  // Build QML string that specifies menu Action to add
                  var qmlStr = 
                     "import QtQuick.Controls 2.3; Action {id: myAction; text: \"" + cmaps[i] + "\"}";
                // Create the menu Action
                 var obj = 
                        Qt.createQmlObject(qmlStr,
                              testMenu,
                             "dynamicAction");
                                  
                 // Add created Action to the menu    
                 testMenu.addAction(obj);
               }
            }
            

            Thanks to @jeremy_k for the suggestion!

            B 1 Reply Last reply
            0
            • Tom assoT Tom asso

              @jeremy_k Thanks- looking at the link you provided, but I cannot find any examples of how Menu.addAction() (and other methods) are actually used in QML code. Do you know of an example? In my case, menu item names are stored in string array cmaps, and my QML looks like:

              Menu {
                 title: "TEST"
                 id: testMenu
                 Component.onCompleted: {
                 // Insert menu items with names 
                 // from cmaps array	
                 for (var i = 0; i < cmaps.length; i++)  { 
                    console.log("map: ", cmaps[i])
                     testMenu.addItem({"text":cmaps[i]});
                 } 
              }
              

              I can see the loop being executed, but items do not appear in the menu - do you know what I am missing? Thanks!

              jeremy_kJ Online
              jeremy_kJ Online
              jeremy_k
              wrote on last edited by
              #6

              @Tom-asso said in "Dynamically" add QML menu items based on C++?:

              @jeremy_k Thanks- looking at the link you provided, but I cannot find any examples of how Menu.addAction() (and other methods) are actually used in QML code. Do you know of an example? In my case, menu item names are stored in string array cmaps, and my QML looks like:

              Menu {
                 title: "TEST"
                 id: testMenu
                 Component.onCompleted: {
                 // Insert menu items with names 
                 // from cmaps array	
                 for (var i = 0; i < cmaps.length; i++)  { 
                    console.log("map: ", cmaps[i])
                     testMenu.addItem({"text":cmaps[i]});
                 } 
              }
              

              I can see the loop being executed, but items do not appear in the menu - do you know what I am missing? Thanks!

              I see that you solved the problem in the following post. Perhaps you figured out the issue in the version above. If not:

              The reason it fails is that addItem() takes a Quick Item, but the code is passing a javascript dictionary object.

              Asking a question about code? http://eel.is/iso-c++/testcase/

              1 Reply Last reply
              1
              • Tom assoT Tom asso

                I solved this with the following implementation, using Qt.createQmlObject() to create an Action and add it to the menu with Menu.addAction():

                Menu {
                  title: "TEST"
                  id: testMenu
                  // Create and add Actions to menu
                  Component.onCompleted: {
                    // Insert menu items here, with number of items 
                    // and item names as specified in the cmaps[] array that was
                    // retrieved from C++
                    for (var i = 0; i < cmaps.length; i++)  {
                      // Build QML string that specifies menu Action to add
                      var qmlStr = 
                         "import QtQuick.Controls 2.3; Action {id: myAction; text: \"" + cmaps[i] + "\"}";
                    // Create the menu Action
                     var obj = 
                            Qt.createQmlObject(qmlStr,
                                  testMenu,
                                 "dynamicAction");
                                      
                     // Add created Action to the menu    
                     testMenu.addAction(obj);
                   }
                }
                

                Thanks to @jeremy_k for the suggestion!

                B Offline
                B Offline
                Bob64
                wrote on last edited by Bob64
                #7

                @Tom-asso I know you have already got a solution, but I wonder if the approach suggested in this link might work for you. The idea is to define your dynamic menu entries by means of a model, and instantiate the items using a repeater. In your case you could expose the model from C++.

                From the link:

                Menu {
                    id:contextMenu
                    visible: true
                    Repeater {
                        model: menuItems
                        MenuItem {
                            text: modelData
                        }
                    }
                }
                

                The example instantiates MenuItem though, rather than Action, and Repeater is documented as only working with Item-based elements, which Action isn't. I don't know if there is a way around this, but if there were some way to get it to work, it would be a more "QML" way of doing it.

                Tom assoT 1 Reply Last reply
                1
                • B Bob64

                  @Tom-asso I know you have already got a solution, but I wonder if the approach suggested in this link might work for you. The idea is to define your dynamic menu entries by means of a model, and instantiate the items using a repeater. In your case you could expose the model from C++.

                  From the link:

                  Menu {
                      id:contextMenu
                      visible: true
                      Repeater {
                          model: menuItems
                          MenuItem {
                              text: modelData
                          }
                      }
                  }
                  

                  The example instantiates MenuItem though, rather than Action, and Repeater is documented as only working with Item-based elements, which Action isn't. I don't know if there is a way around this, but if there were some way to get it to work, it would be a more "QML" way of doing it.

                  Tom assoT Offline
                  Tom assoT Offline
                  Tom asso
                  wrote on last edited by
                  #8

                  @Bob64 - Thanks. In my application, the qml doesn't "know" the list of menu item names, which is provided by C++. But the C++ does not change that name list while the application is running, so it seems a bit more complex to use model rather than just a string array of names.

                  1 Reply Last reply
                  0
                  • jeremy_kJ Online
                    jeremy_kJ Online
                    jeremy_k
                    wrote on last edited by
                    #9

                    @Tom-asso said in "Dynamically" add QML menu items based on C++?:

                    @Bob64 - Thanks. In my application, the qml doesn't "know" the list of menu item names, which is provided by C++. But the C++ does not change that name list while the application is running, so it seems a bit more complex to use model rather than just a string array of names.

                    A list is a valid model for Quick items that take a model.

                    import QtQuick
                    import QtQuick.Controls
                    import QtQml.Models
                    Window {
                        width: 100
                        height: 50
                        visible: true
                        Menu {
                            id: menu
                            Instantiator {
                                model: ["first", "second"]
                                delegate: MenuItem { text: modelData }
                                onObjectAdded: (index, object) => menu.insertItem(index, object)
                            }
                            Component.onCompleted: popup()
                        }
                    }
                    

                    Asking a question about code? http://eel.is/iso-c++/testcase/

                    GrecKoG 1 Reply Last reply
                    2
                    • jeremy_kJ jeremy_k

                      @Tom-asso said in "Dynamically" add QML menu items based on C++?:

                      @Bob64 - Thanks. In my application, the qml doesn't "know" the list of menu item names, which is provided by C++. But the C++ does not change that name list while the application is running, so it seems a bit more complex to use model rather than just a string array of names.

                      A list is a valid model for Quick items that take a model.

                      import QtQuick
                      import QtQuick.Controls
                      import QtQml.Models
                      Window {
                          width: 100
                          height: 50
                          visible: true
                          Menu {
                              id: menu
                              Instantiator {
                                  model: ["first", "second"]
                                  delegate: MenuItem { text: modelData }
                                  onObjectAdded: (index, object) => menu.insertItem(index, object)
                              }
                              Component.onCompleted: popup()
                          }
                      }
                      
                      GrecKoG Online
                      GrecKoG Online
                      GrecKo
                      Qt Champions 2018
                      wrote on last edited by GrecKo
                      #10

                      An Instantiator is not needed, Menu can handle dynamically added MenuItem by a Repeater.
                      Use the code provided by bob64.
                      And like jeremy_k said you don't have to pass it a full fledged QAbstractItemModel, a string list is fine.

                      jeremy_kJ 1 Reply Last reply
                      0
                      • GrecKoG GrecKo

                        An Instantiator is not needed, Menu can handle dynamically added MenuItem by a Repeater.
                        Use the code provided by bob64.
                        And like jeremy_k said you don't have to pass it a full fledged QAbstractItemModel, a string list is fine.

                        jeremy_kJ Online
                        jeremy_kJ Online
                        jeremy_k
                        wrote on last edited by
                        #11

                        @GrecKo said in "Dynamically" add QML menu items based on C++?:

                        An Instantiator is not needed, Menu can handle dynamically added MenuItem by a Repeater.

                        Except that as @Bob64 points out, Repeater cannot handle non-Item delegates. It will work for MenuItem, but not Menu or Action.

                        Asking a question about code? http://eel.is/iso-c++/testcase/

                        GrecKoG 1 Reply Last reply
                        0
                        • jeremy_kJ jeremy_k

                          @GrecKo said in "Dynamically" add QML menu items based on C++?:

                          An Instantiator is not needed, Menu can handle dynamically added MenuItem by a Repeater.

                          Except that as @Bob64 points out, Repeater cannot handle non-Item delegates. It will work for MenuItem, but not Menu or Action.

                          GrecKoG Online
                          GrecKoG Online
                          GrecKo
                          Qt Champions 2018
                          wrote on last edited by
                          #12

                          @jeremy_k not working with Action is not really an issue since you are in charge of chosing the delegate type, so you can create a MenuItem instead (that's what the Menu does anyway when adding an Action).

                          Instantiator is indeed needed for nested Menus.

                          1 Reply Last reply
                          0

                          • Login

                          • Login or register to search.
                          • First post
                            Last post
                          0
                          • Categories
                          • Recent
                          • Tags
                          • Popular
                          • Users
                          • Groups
                          • Search
                          • Get Qt Extensions
                          • Unsolved