Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt
  • Unsolved
Collapse
qtws26_logo

The Qt Event of the Year: Qt World Summit 2026

Save Your Spot >
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. "Dynamically" add QML menu items based on C++?
Qt 6.12 LTS is out! See what's new in the release blog

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

Scheduled Pinned Locked Moved Unsolved QML and Qt Quick
12 Posts 4 Posters 4.0k Views 1 Watching
  • 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.
  • jeremy_kJ Offline
    jeremy_kJ Offline
    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 Offline
            jeremy_kJ Offline
            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 Offline
                  jeremy_kJ Offline
                  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 Offline
                    GrecKoG Offline
                    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 Offline
                      jeremy_kJ Offline
                      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 Offline
                        GrecKoG Offline
                        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
                        • Unsolved