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. specifying Button:onClicked via property
QtWS25 Last Chance

specifying Button:onClicked via property

Scheduled Pinned Locked Moved Solved QML and Qt Quick
13 Posts 6 Posters 3.6k 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.
  • M Offline
    M Offline
    mzimmers
    wrote on 30 Nov 2022, 23:42 last edited by
    #1

    Hi all -

    I'm implementing an app that will make copious use of customized buttons (really Rectangles with MouseAreas, probably). I need to be able to specify for each of my buttons what behavior to take when clicked. Can I do this using a property? If not, does anyone have a recommendation?

    Rectangle {
        id: pill
    
        // stuff
        
        MouseArea {
            anchors.fill: parent
            onClicked: // what do I put here?
        }
    }
    

    Thanks...

    B 1 Reply Last reply 1 Dec 2022, 15:59
    0
    • J Offline
      J Offline
      JoeCFD
      wrote on 30 Nov 2022, 23:51 last edited by JoeCFD
      #2

      Can not you simply inherit a button for example:

      TabButton  {
          id: root
          background: Rectangle {
              width: root.width
              height: root.height
              color: root.checked ? StyleSheet.mainActive : StyleSheet.greyBackground
          }
      
          onClicked: {
              if ( root.checked ) {
                  ----------switch pane----------
              }
          }
      }
      
      1 Reply Last reply
      0
      • M Offline
        M Offline
        mzimmers
        wrote on 1 Dec 2022, 00:02 last edited by
        #3

        My custom button is going to have to be fairly "open" when it comes to the onClicked() activity:

        • push something onto a stack
        • pop something off of a stack
        • send a signal of some kind back to the C++ code
        • etc.

        I really need to parameterize the action (if this is possible).

        L 1 Reply Last reply 1 Dec 2022, 07:35
        0
        • M mzimmers
          1 Dec 2022, 00:02

          My custom button is going to have to be fairly "open" when it comes to the onClicked() activity:

          • push something onto a stack
          • pop something off of a stack
          • send a signal of some kind back to the C++ code
          • etc.

          I really need to parameterize the action (if this is possible).

          L Offline
          L Offline
          lemons
          wrote on 1 Dec 2022, 07:35 last edited by
          #4

          @mzimmers if you want to add an onClicked signal to your rectangle:

          // Pill.qml
          Rectangle {
              id: pill
              signal clicked
          
              MouseArea {
                  anchors.fill: parent
                  onClicked: pill.clicked()
              }
          }
          
          // main.qml
          Pill {
              width: 200
              height: 200
              color: "red"
              onClicked: {
                  console.debug("pill clicked")
              }
          }
          

          if you want to pass an action as parameter to the object:

          // Pill.qml
          Rectangle {
              id: pill
              property var action: function () {}
          
              MouseArea {
                  anchors.fill: parent
                  onClicked: action()
              }
          }
          
          // main.qml
          Pill {
              width: 200
              height: 200
              color: "red"
              action: function () {
                  console.debug("action passed to mousearea of pill")
              }
          }
          
          1 Reply Last reply
          2
          • G Offline
            G Offline
            GrecKo
            Qt Champions 2018
            wrote on 1 Dec 2022, 11:18 last edited by
            #5

            Just customize a QQC2 button, don't recreate your own from scratch.

            M 1 Reply Last reply 1 Dec 2022, 15:04
            0
            • G GrecKo
              1 Dec 2022, 11:18

              Just customize a QQC2 button, don't recreate your own from scratch.

              M Offline
              M Offline
              mzimmers
              wrote on 1 Dec 2022, 15:04 last edited by
              #6

              @GrecKo I don't see how that would solve my problem.

              G 1 Reply Last reply 3 Dec 2022, 15:30
              0
              • M mzimmers
                30 Nov 2022, 23:42

                Hi all -

                I'm implementing an app that will make copious use of customized buttons (really Rectangles with MouseAreas, probably). I need to be able to specify for each of my buttons what behavior to take when clicked. Can I do this using a property? If not, does anyone have a recommendation?

                Rectangle {
                    id: pill
                
                    // stuff
                    
                    MouseArea {
                        anchors.fill: parent
                        onClicked: // what do I put here?
                    }
                }
                

                Thanks...

                B Offline
                B Offline
                Bob64
                wrote on 1 Dec 2022, 15:59 last edited by Bob64 12 Jan 2022, 16:01
                #7

                @mzimmers if I understand what you want correctly, all you need to do is to expose a property in your root component (or maybe a property alias to the mouse area's onClicked property) that expects to be assigned an on-clicked handler function:

                MyButton.qml

                Rectangle {
                    id: pill
                    property var onClickedHandler
                    // stuff
                    
                    MouseArea {
                        anchors.fill: parent
                        onClicked: pill.onClickedHandler()
                    }
                }
                

                Usage:

                     function handler1() { ... }
                     function handler2() { ... }
                     ...
                     MyButton {
                        id: but1
                        onClickedHandler: handler1
                     }
                     MyButton {
                        id: but2
                        onClickedHandler: handler2
                     }
                
                M 1 Reply Last reply 1 Dec 2022, 16:51
                1
                • B Bob64
                  1 Dec 2022, 15:59

                  @mzimmers if I understand what you want correctly, all you need to do is to expose a property in your root component (or maybe a property alias to the mouse area's onClicked property) that expects to be assigned an on-clicked handler function:

                  MyButton.qml

                  Rectangle {
                      id: pill
                      property var onClickedHandler
                      // stuff
                      
                      MouseArea {
                          anchors.fill: parent
                          onClicked: pill.onClickedHandler()
                      }
                  }
                  

                  Usage:

                       function handler1() { ... }
                       function handler2() { ... }
                       ...
                       MyButton {
                          id: but1
                          onClickedHandler: handler1
                       }
                       MyButton {
                          id: but2
                          onClickedHandler: handler2
                       }
                  
                  M Offline
                  M Offline
                  mzimmers
                  wrote on 1 Dec 2022, 16:51 last edited by
                  #8

                  @Bob64 @lemons thanks; this will work. I wonder -- is it possible to avoid using a function for this? No big deal if it isn't; it would just simplify the coding a bit.

                  B 1 Reply Last reply 1 Dec 2022, 17:47
                  0
                  • M mzimmers
                    1 Dec 2022, 16:51

                    @Bob64 @lemons thanks; this will work. I wonder -- is it possible to avoid using a function for this? No big deal if it isn't; it would just simplify the coding a bit.

                    B Offline
                    B Offline
                    Bob64
                    wrote on 1 Dec 2022, 17:47 last edited by
                    #9

                    @mzimmers I think you mean just to use a "Javascript block" (not sure of technical term) like this:

                         onClickHandler: {
                            // do stuff
                         }
                    

                    and have that passed down to the onClicked property of the MouseArea?

                    I don't think that would work, though I can't explain the technicalities of it. You can almost get there with an "inline" function of some description though. If you have a later version of Qt than I have, I think you can use JS "arrow functions" like this:

                         onClickHandler: () => {
                            // do stuff
                         }
                    

                    (If the function had arguments, they would go in the () but here it's an empty arg list.)

                    The older approach to do something similar is the anonymous function:

                         onClickHandler: function() {
                            // do stuff
                         }
                    
                    M 1 Reply Last reply 1 Dec 2022, 17:53
                    0
                    • B Bob64
                      1 Dec 2022, 17:47

                      @mzimmers I think you mean just to use a "Javascript block" (not sure of technical term) like this:

                           onClickHandler: {
                              // do stuff
                           }
                      

                      and have that passed down to the onClicked property of the MouseArea?

                      I don't think that would work, though I can't explain the technicalities of it. You can almost get there with an "inline" function of some description though. If you have a later version of Qt than I have, I think you can use JS "arrow functions" like this:

                           onClickHandler: () => {
                              // do stuff
                           }
                      

                      (If the function had arguments, they would go in the () but here it's an empty arg list.)

                      The older approach to do something similar is the anonymous function:

                           onClickHandler: function() {
                              // do stuff
                           }
                      
                      M Offline
                      M Offline
                      mzimmers
                      wrote on 1 Dec 2022, 17:53 last edited by
                      #10

                      @Bob64 good input. What I was originally thinking of was something like:

                      Rectangle {
                          id: pill
                          property var doStuff
                          // stuff
                          
                          MouseArea {
                              anchors.fill: parent
                              onClicked: doStuff
                          }
                      }
                      

                      But stepping back, I think I'm trying to do something that will create more work than it will solve.

                      1 Reply Last reply
                      0
                      • M mzimmers
                        1 Dec 2022, 15:04

                        @GrecKo I don't see how that would solve my problem.

                        G Offline
                        G Offline
                        GrecKo
                        Qt Champions 2018
                        wrote on 3 Dec 2022, 15:30 last edited by
                        #11

                        @mzimmers said in specifying Button:onClicked via property:

                        @GrecKo I don't see how that would solve my problem.

                        A Button already has a clicked signal.
                        If you only want to customize the look of your button, inherit from a base Button and change the contentItem and/or the background property of it.

                        \\ MyCustomButton.qml
                         import QtQuick.Controls
                        Button {
                            id: control
                            background: // ...
                            contentItem: // ...
                        }
                        

                        Then you don't have to do anything special for the click and just use it like so:

                        MyCustomButton {
                           onClicked: doSomething();
                        }
                        

                        You don't need more than that. This onClickedHandler is superfluous.
                        And you still have access to the Qt Quick Controls features like font and style inheriting, padding, inset, clickPolicy, etc..

                        M 1 Reply Last reply 3 Dec 2022, 15:35
                        0
                        • G GrecKo
                          3 Dec 2022, 15:30

                          @mzimmers said in specifying Button:onClicked via property:

                          @GrecKo I don't see how that would solve my problem.

                          A Button already has a clicked signal.
                          If you only want to customize the look of your button, inherit from a base Button and change the contentItem and/or the background property of it.

                          \\ MyCustomButton.qml
                           import QtQuick.Controls
                          Button {
                              id: control
                              background: // ...
                              contentItem: // ...
                          }
                          

                          Then you don't have to do anything special for the click and just use it like so:

                          MyCustomButton {
                             onClicked: doSomething();
                          }
                          

                          You don't need more than that. This onClickedHandler is superfluous.
                          And you still have access to the Qt Quick Controls features like font and style inheriting, padding, inset, clickPolicy, etc..

                          M Offline
                          M Offline
                          mzimmers
                          wrote on 3 Dec 2022, 15:35 last edited by
                          #12

                          @GrecKo OK, now I see what you're saying, and I agree that would make things a little easier. I'm wondering how much I can customize the button: can I have multiple lines of text? And, if necessary, use multiple fonts/sizes for the text?

                          Thanks...

                          1 Reply Last reply
                          0
                          • johngodJ Offline
                            johngodJ Offline
                            johngod
                            wrote on 13 Dec 2022, 23:49 last edited by
                            #13

                            I know this is marked as solved but just wanted to add my 2 cents.
                            I did this by adding a property int type and a signal with a argument in my button, then calling the mouse click handler would invoke the signal with the type argument. Then outside on your menu were you have all your buttons, each button click will call another menu signal that receives the button type. Then you just add a bunch of if else's or a switch case to handle every type of button. Something like this:
                            Pill.qml:

                            Rectangle {
                                id: pill
                                property int type
                                signal btnClick(btnSignal: int)
                                
                                MouseArea {
                                    anchors.fill: parent
                                    onClicked: btnClick(type)
                                }
                            }
                            

                            Then on your menu:

                            signal handlePills(type: int) 
                            
                            onHandlePills: function(type){
                                if (type === stuff1)
                                    doStuff1()
                            
                                if (type === stuff2)
                                    doStuff2()
                            .......
                            }
                            
                            
                            Pill {
                                type: stuff1
                                onBtnClick: handlePills(type)
                            }
                            
                            Pill {
                                type: stuff2
                                onBtnClick: handlePills(type)
                            }
                            

                            To make this more elegant you can create a qml enum and use it on type. I dont know your use case but to me was less error prone and more elegant code.

                            Taking another step further, and since I needed a dynamic menu where I could add or remove buttons, I created a listview, a model and button delegate, to create the menu with buttons. Then only took me a line of code to add a button:

                            function showMenuCommands() {
                                    menuCommands.modelMenu.clear()
                                    menuCommands.modelMenu.append({"textName": "copy", "typeName": Commands.Copy})
                                    menuCommands.modelMenu.append({"textName": "move", "typeName": Commands.Move})
                                    menuCommands.modelMenu.append({"textName": "scale", "typeName": Commands.Scale})
                                    ........
                                }
                            
                            1 Reply Last reply
                            1

                            • Login

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