1

Inspired by the following thread: PyQt: How to set Combobox Items be Checkable?
I was able to create a simple checkable "combobox" by using a QToolButton and adding checkable items to it using addAction. See simple code example:

from PyQt4 import QtCore, QtGui
import sys
class Ui_Dialog(object):
   def setupUi(self, Dialog):
       Dialog.setObjectName("Dialog")
       Dialog.resize(198, 157)
       self.toolButton = QtGui.QToolButton(Dialog)
       self.toolButton.setGeometry(QtCore.QRect(60, 50, 71, 19))
       self.toolButton.setObjectName("toolButton")
       self.toolButton.setText("MyButton")
       QtCore.QMetaObject.connectSlotsByName(Dialog)

class MyDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.toolMenu = QtGui.QMenu(self.ui.toolButton)
        for i in range(3):
            action = self.toolMenu.addAction("Category " + str(i))
            action.setCheckable(True)
        self.ui.toolButton.setMenu(self.toolMenu)
        self.ui.toolButton.setPopupMode(QtGui.QToolButton.InstantPopup)

if __name__ == "__main__":
    app = QtGui.QApplication(sys.argv)
    myapp = MyDialog()
    myapp.show()
    sys.exit(app.exec_())  

But how can I capture which of the QToolButton actions (i.e. Category 1 and/or Category 2/3) that has been checked in my dialog?

Community
  • 1
  • 1
emblixt
  • 13
  • 4

2 Answers2

1

Alternatively you can define your QActionGroup to collect all of your actions, then connect the signal triggered to callback method, this way:

class MyDialog(QtGui.QDialog):
    def __init__(self, parent=None):
        QtGui.QWidget.__init__(self, parent)
        self.ui = Ui_Dialog()
        self.ui.setupUi(self)
        self.toolMenu = QtGui.QMenu(self.ui.toolButton)
        group = QtGui.QActionGroup(self.toolMenu)
        for i in range(3):
            action = self.toolMenu.addAction("Category %d" % i)
            action.setCheckable(True)
            action.setActionGroup(group)
            action.setData(i)
        self.ui.toolButton.setMenu(self.toolMenu)
        self.ui.toolButton.setPopupMode(QtGui.QToolButton.InstantPopup)
        group.triggered.connect(self.test)

    def test(self, act):
        print 'Action' , act.data().toInt()[0]

Here in test() method, reading the data of each action returns a QVariant which you need to convert it back to int using toInt method returning (int, bool) tuple, thus [0]

Iron Fist
  • 10,739
  • 2
  • 18
  • 34
  • 1
    Note that with the second version of [PyQt API](http://pyqt.sourceforge.net/Docs/PyQt4/pyqt_qvariant.html) (by default in Python 3), `QVariant` are automatically converted to python types. – Mel Dec 11 '15 at 08:56
  • This solution made the toolButton to only accept one action, so I can't make a multiselection of actions. – emblixt Dec 14 '15 at 06:45
0

First we need to loop through the actions of the menu.There's no convenience function to do this, but every widget has a method findChildren. To get a list of all the children of type QAction, you do:

 self.toolMenu.findChildren(QtGui.QAction)

For every action, we can use QAction.isChecked() to get a boolean.

Full example:

def whatIsChecked(self):
    for action in self.toolMenu.findChildren(QtGui.QAction):
        if action.isChecked():
            print(action.text(),"is checked")
        else:
            print(action.text(),"is not checked")
Mel
  • 5,837
  • 10
  • 37
  • 42