Results 1 to 5 of 5

Thread: How to find the control that triggered a QAction

  1. #1
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default How to find the control that triggered a QAction

    I have a bunch of sliders. When I create the sliders I give them each a name with .setObjectName and add a set of actions with .addActions.

    When I right click on a slider it does as expected and calls the code specified by the definition of the action. In this case it is the same code for each action and that code dispatches to the appropriate code for the action.

    How do I find the slider that actually triggered the action? (i.e. I need to read the value of the slider) (when I call .sender().objectName() it returns an empty string)

  2. #2
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,120
    Thanks
    235
    Thanked 656 Times in 646 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to find the control that triggered a QAction

    If your slot is connected to the QAction's triggered() signal, then sender() is the QAction instance, not the widget to which you added it. I don't know if there is any way to recover the pointer to the widget.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  3. #3
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: How to find the control that triggered a QAction

    What I want to do is pop a list when the user right clicks on the slider offering some optional things to do. All the sliders will do the same thing, but just act on the slider that was right clicked.

    I got, what I assume is a kludge way of doing it, working:

    In the init for the dialog:

    Qt Code:
    1. self.slider_entered = ''
    2. self.sldr_actions_list = []
    3. self.sldr_action_names = ['Set Min', 'Set 0db', 'Propagate level']
    4. for action_name in self.sldr_action_names:
    5.  
    6. newaction = QAction(action_name, None)
    7. newaction.triggered.connect(eval('self.slider_action_{}'.format(action_name.replace(' ', '_').lower())))
    8. self.sldr_actions_list.append(newaction)
    To copy to clipboard, switch view to plain text mode 

    When the slider is added:
    Qt Code:
    1. sldr = MySlider()
    2. sldr.setContextMenuPolicy(Qt.ActionsContextMenu)
    3. sldr.addActions(self.sldr_actions_list)
    To copy to clipboard, switch view to plain text mode 

    MySlider inherits from QSLider and has:

    Qt Code:
    1. def enterEvent(self, m_ev):
    2. self.window().slider_entered = self.objectName()
    To copy to clipboard, switch view to plain text mode 

    and the code for the actions in the dialog, set min in this case:

    Qt Code:
    1. def slider_action_set_min(self):
    2. act_sndr = self.sender()
    3. sldr = self.window().findChild(QtWidgets.QSlider, name=self.slider_entered)
    4. print('Set slider to min. Current value: {}'.format(sldr.value()))
    5. self.slider_set(self.slider_entered, 0)
    To copy to clipboard, switch view to plain text mode 

    What I want to do is pop a list when the user right clicks on the slider offering some optional things to do. All the sliders will do the same thing, but just act on the slider that was right clicked.

    I got, what I assume is a kludge way of doing it, working:

    In the init for the dialog:

    Qt Code:
    1. self.slider_entered = ''
    2. self.sldr_actions_list = []
    3. self.sldr_action_names = ['Set Min', 'Set 0db', 'Propagate level']
    4. for action_name in self.sldr_action_names:
    5.  
    6. newaction = QAction(action_name, None)
    7. newaction.triggered.connect(eval('self.slider_action_{}'.format(action_name.replace(' ', '_').lower())))
    8. self.sldr_actions_list.append(newaction)
    To copy to clipboard, switch view to plain text mode 

    When the slider is added:
    Qt Code:
    1. sldr = MySlider()
    2. sldr.setContextMenuPolicy(Qt.ActionsContextMenu)
    3. sldr.addActions(self.sldr_actions_list)
    To copy to clipboard, switch view to plain text mode 

    MySlider inherits from QSLider and has:

    Qt Code:
    1. def enterEvent(self, m_ev):
    2. self.window().slider_entered = self.objectName()
    To copy to clipboard, switch view to plain text mode 

    and the code for the actions in the dialog, set min in this case:

    Qt Code:
    1. def slider_action_set_min(self):
    2. act_sndr = self.sender()
    3. sldr = self.window().findChild(QtWidgets.QSlider, name=self.slider_entered)
    4. print('Set slider to min. Current value: {}'.format(sldr.value()))
    5. self.slider_set(self.slider_entered, 0)
    To copy to clipboard, switch view to plain text mode 


    Added after 1 30 minutes:


    I think I found the right way (or at least a better way)

    When I create the slider:

    Qt Code:
    1. sldr.setContextMenuPolicy(Qt.CustomContextMenu)
    2. sldr.customContextMenuRequested.connect(self.sldr_action_click)
    To copy to clipboard, switch view to plain text mode 

    then the self.sender() in self.sldr_action_click is the slider.
    Last edited by drmacro; 23rd July 2017 at 16:24.

  4. #4
    Join Date
    Jan 2008
    Location
    Alameda, CA, USA
    Posts
    4,120
    Thanks
    235
    Thanked 656 Times in 646 Posts
    Qt products
    Qt5
    Platforms
    Windows Android

    Default Re: How to find the control that triggered a QAction

    I think I found the right way (or at least a better way)
    Yep, that's it.

    From what I understand of your previous (kludge) code, it appeared to have a pretty big memory leak since it looks like the QAction instances are created every time the slider is entered, but they're never deleted. I'm not a Python expert, so my reading of your code might be wrong.
    <=== The Great Pumpkin says ===>
    Please use CODE tags when posting source code so it is more readable. Click "Go Advanced" and then the "#" icon to insert the tags. Paste your code between them.

  5. The following user says thank you to d_stranz for this useful post:

    drmacro (23rd July 2017)

  6. #5
    Join Date
    Oct 2015
    Posts
    45
    Thanks
    8
    Qt products
    Qt5
    Platforms
    Unix/X11

    Default Re: How to find the control that triggered a QAction

    From what I understand of your previous (kludge) code, it appeared to have a pretty big memory leak since it looks like the QAction instances are created every time the slider is entered, but they're never deleted. I'm not a Python expert, so my reading of your code might be wrong.
    I thought only the string self.slider_entered was set every time the widget was entered...

    But, I'm not a python expert either (maybe semi-seasoned hack...on a good day ). I could have watched for memory growth to see but Ive changed the code over to the better way and not going back now...

Similar Threads

  1. Modify triggered signal on QAction
    By Marcofe in forum Newbie
    Replies: 4
    Last Post: 28th October 2013, 12:31
  2. Replies: 7
    Last Post: 7th September 2013, 13:35
  3. QAction, triggered signal dont call a slot
    By kaszewczyk in forum Newbie
    Replies: 6
    Last Post: 5th October 2010, 21:30
  4. Replies: 8
    Last Post: 10th December 2009, 10:06
  5. Replies: 2
    Last Post: 27th February 2007, 21:06

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.